AsAssembly · Lesson 1 of 10

How CPUs Actually Work

Before writing a single line, you need a mental model of what the CPU is doing. Everything in assembly makes sense once you understand registers, memory, and the fetch-decode-execute cycle.

A CPU is a machine that reads instructions from memory one at a time, executes them, and moves to the next. An instruction might be "add two numbers," "copy a value from memory," or "jump to a different instruction." That's it. Everything your computer does — 3D games, video calls, AI — reduces to sequences of these tiny operations.

Registers are small, fast storage locations inside the CPU itself. x86-64 has 16 general-purpose registers: rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, and r8–r15. Each holds 64 bits (8 bytes). Operations on registers are the fastest thing the CPU can do — no memory access required.

x86-64 ASM
; x86-64 general-purpose registers and their conventional uses:
; rax — accumulator: return values, arithmetic results
; rbx — base: callee-saved (must preserve across function calls)
; rcx — counter: loop counters, 4th argument
; rdx — data: I/O, 3rd argument
; rsi — source index: string source, 2nd argument
; rdi — destination index: string dest, 1st argument
; rbp — base pointer: stack frame base (callee-saved)
; rsp — stack pointer: always points to top of stack
; r8–r11  — 5th–8th arguments, caller-saved
; r12–r15 — callee-saved scratch registers

; Each 64-bit register has sub-register aliases:
; rax  = 64-bit (the full register)
; eax  = lower 32 bits
; ax   = lower 16 bits
; al   = lower 8 bits
; ah   = bits 8-15

; Example: after  mov rax, 0x0000000100FF
;   rax = 0x0000000100FF
;   eax = 0x000100FF
;   ax  = 0x00FF
;   al  = 0xFF
;   ah  = 0x00

Memory is a huge array of bytes, each with an address (a 64-bit number on x86-64). To use data in memory, you load it into a register, operate on it, then store it back. The stack is a region of memory that grows downward — rsp points to the current top. The heap is where malloc lives. Code lives in the text segment.

x86-64 ASM
; Memory layout of a running program (low address at top):
;
;  0x0000...  ──────────────────────
;             │  text segment        │  your compiled code (read + execute)
;             ├──────────────────────┤
;             │  data segment        │  initialized globals (read + write)
;             ├──────────────────────┤
;             │  bss segment         │  uninitialized globals (zero-filled)
;             ├──────────────────────┤
;             │  heap                │  grows upward (malloc/free)
;             │         ↓            │
;             │  (free space)        │
;             │         ↑            │
;             │  stack               │  grows downward
;  0xFFFF...  ──────────────────────
;
; rsp always points to the last pushed value on the stack.
; push rax  →  rsp -= 8, then [rsp] = rax
; pop  rax  →  rax = [rsp], then rsp += 8
✦ Tip
Assembly is architecture-specific. x86-64 (what you run on your laptop and most servers) is what we cover here. ARM64 (your phone, Apple Silicon, Raspberry Pi) has a cleaner instruction set but different syntax and conventions. The concepts transfer; the specifics do not.