CPU Registers, PC, SP, Status, Instruction Execution
This chapter introduces the CPU as a machine: registers, the program counter, the stack pointer, status flags, and the fetch-decode-execute cycle.
Why This Matters
C is close to the machine, and understanding the CPU is what makes "close to the machine" concrete. This chapter is the foundation for reading assembly, understanding calling conventions, and reasoning about performance.
Prerequisites
c.opt.1— how optimizers work.
Core Concept
A CPU executes instructions in a loop:
1. Fetch the instruction at the program counter (PC). 2. Decode it. 3. Execute it (load/store/ALU/branch). 4. Update the PC to the next instruction (or a branch target).
Registers
Registers are fast, small storage inside the CPU. They hold operands, addresses, and intermediate results. A CPU has a fixed set, each with a role.
Program counter (PC)
The PC holds the address of the next instruction to execute. On x86-64 it is RIP; on ARM64 it is PC (or X30 for return address).
Stack pointer (SP)
The SP points to the top of the call stack. It grows/shrinks with function calls (c.cpu.2).
Status register
The status register holds condition flags (zero, carry, sign, overflow) set by arithmetic and used by conditional branches.
Examples
x86-64 registers (selected)
| Register | Role |
|---|---|
RAX | return value, accumulator |
RSP | stack pointer |
RBP | base/frame pointer (often omitted) |
RIP | program counter |
RDI–R9 | argument registers (System V) |
ARM64 registers (selected)
| Register | Role |
|---|---|
X0–X7 | argument/return registers |
X29 | frame pointer |
X30 | link (return) register |
SP | stack pointer |
PC | program counter |
How It Works
add rax, rbx reads rax and rbx, adds them, and writes rax, updating status flags. A cmp sets flags; a conditional jne reads them to decide the next PC. Loads/stores move data between registers and memory.
Variations
Load/store vs. memory-memory
Most modern ISAs are load/store: arithmetic operates on registers, and separate instructions move data to/from memory.
CISC vs. RISC
x86 is CISC (complex instructions); ARM/RISC-V are RISC (simpler, uniform instructions). The concepts (PC, SP, flags) apply to both.
Common Mistakes
- Confusing the stack pointer with the program counter.
- Assuming a specific register count/name is universal.
Undefined Behavior
- CPU behavior is hardware, not ISO C. C-level UB can cause the compiler to
emit code that, at the CPU level, does something surprising.
Portability
- Registers, instruction sets, and flags are architecture-specific.
Under the Hood
The CPU pipeline fetches/decode/executes, with branch prediction and out-of-order execution (c.cpu.3). The compiler maps C operations onto these instructions (c.cpu.6).
Practical Usage
- Read assembly to understand what the compiler emitted.
- Use
info registersin GDB to inspect CPU state.
Exercises
1. In GDB, stop a program and inspect info registers; identify PC and SP. 2. Disassemble a tiny function and trace the fetch-decode-execute of each instruction. 3. Compare the register sets of x86-64 and ARM64 (from docs).
Deep Challenge
Explain how a conditional branch is implemented using status flags, and show how a C if (a < b) becomes a compare + conditional branch in assembly.
Related Concepts
c.cpu.2— stack frames.c.cpu.6— C-to-assembly.c.cpu.3— caches and out-of-order.
References
- x86-64/ARM64 architecture manuals.
Verification
- CPU register/PC/SP/flag behavior is hardware architecture.
HARDWARE - No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] Registers
- [ ] Program counter
- [ ] Stack pointer
- [ ] Status flags
- [ ] Fetch-decode-execute
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.cpu.registers | 0 | 6 |
| c.cpu.pc | 0 | 5 |
| c.cpu.sp | 0 | 5 |
| c.cpu.status | 0 | 5 |
| c.cpu.execution | 0 | 6 |