awesome-everything RU
↑ Back to the climb

Base CS from zero

Registers

Crux Registers are a small set of named, ultra-fast storage slots physically inside the CPU. The CPU does its actual arithmetic and logic on values held in registers, not in main memory. The program counter is itself a register.
◷ 20 min

In the previous lessons you have seen references to “R0” and “R1” — named slots where the CPU keeps values while doing arithmetic. In the fetch–decode–execute cycle you saw that the program counter is also a named slot that holds the address of the next instruction.

These slots are called registers. They are the CPU’s working memory — the values the CPU is actually computing on right now. Without registers, the CPU would have to reach into main memory for every single intermediate value, which would make every program hundreds of times slower.

What exactly are registers, how many does a CPU have, and why does their existence make programs fast?

Goal

After this lesson you can define a register as an ultra-fast storage slot inside the CPU, explain why registers exist (memory is far and slow), describe what general-purpose and special-purpose registers are, and confirm that the program counter is itself a register.

1

What a register is. A register is a storage location built directly into the CPU chip, not in the separate memory (RAM) chips. Each register holds exactly one value — on a 64-bit CPU, one register holds a 64-bit (8-byte) value.

Registers are made from the same kind of transistor circuits as the logic inside the CPU. They sit on the same piece of silicon, millimetres or even micrometres from the ALU that does the arithmetic. Accessing a register takes one or two clock cycles — roughly a fraction of a nanosecond on a modern CPU.

Main memory (RAM), by contrast, is a separate chip connected by a bus. Accessing RAM takes 50–100 nanoseconds — roughly 100 to 300 times longer than accessing a register. For repeated computations, that difference is enormous.

2

Why registers exist: memory is far and slow. Consider a loop that adds 1 million numbers together. If the CPU had to fetch each partial sum from RAM, update it, and write it back, every single addition would pay the ~100 ns RAM access cost. That is 100 ms just for memory traffic.

Instead, the CPU loads the current sum into a register once, adds each new number from RAM into the register, and writes the final sum back to RAM once at the end. The register holds the intermediate value at CPU speed. The expensive RAM access happens only twice (once to load the initial sum, once to store the final result).

This is the core principle: bring data to the CPU’s neighbourhood, work on it there, then send the result back. Registers are the “neighbourhood.”

3

General-purpose registers. Most of a CPU’s registers are general-purpose registers (GPRs). They have no fixed meaning — any instruction can use any GPR to hold any value. The programmer (or compiler) decides which register holds which value at any given moment.

Real CPUs have a fixed number of GPRs:

  • An x86-64 CPU has 16 general-purpose 64-bit registers, named RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP, and R8 through R15.
  • An ARM (AArch64) CPU has 31 general-purpose 64-bit registers, named X0 through X30.
  • The simplified toy CPUs in teaching environments (like nand2tetris) may have only a handful: R0, R1, R2, R3.

The number is small and fixed by the chip design. If a program needs more live values than there are registers, the compiler must “spill” some values to memory temporarily and reload them when needed — a necessary cost that compilers work hard to minimise.

Why this works

Why not just have more registers? Adding more registers means more transistors on the chip, which increases power consumption and heat. More importantly, each instruction encoding must name which registers it uses; more registers require more bits per instruction to name them. A 4-bit register field in an instruction can name 16 registers. A 5-bit field names 32. Wider instructions mean larger code size in memory. There is a diminishing-returns trade-off: going from 4 to 16 registers helps a lot; going from 64 to 128 helps much less because compilers already handle 64 efficiently. Most architectures land between 16 and 32 GPRs.

4

Special-purpose registers. Not all registers are general-purpose. A CPU also has several special-purpose registers that have a dedicated function in the hardware:

  • Program Counter (PC) — as you learned in the previous lesson, the PC holds the address of the next instruction to fetch. The CPU updates it automatically after every instruction. A JUMP instruction writes a new value into the PC. It is a register like any other, but it is not available for general use.

  • Stack Pointer (SP) — holds the address of the top of the call stack in memory. Push and pop operations adjust the stack pointer automatically. You will meet the call stack in a later unit.

  • Flags Register (Status Register) — a collection of single-bit flags that record the outcome of the last operation: whether the result was zero, whether there was a carry out of the top bit (overflow), whether the result was negative, and so on. Conditional JUMP instructions consult the flags to decide whether to branch.

  • Instruction Register (IR) — holds the currently executing instruction after it is fetched from memory, as you saw in the fetch–decode–execute cycle.

Common mistake

A common confusion is treating registers and memory (RAM) as two versions of the same thing that differ only in speed. They differ in kind. RAM is a large, addressable array of bytes that persists — its contents survive across function calls and are shared between different programs (via the OS). Registers are a tiny, named, non-addressable set of slots that belong entirely to the currently running instruction stream. You cannot “address” a register with a memory address; you name it directly in the instruction encoding. And when a program saves state to a file or sends data over a network, the data must pass through memory — it never passes through a register directly.

42
R0
7
R1
0
R2
108
PC
0100
IR
0010
Flags
A CPU's register file: R0 holds 42, R1 holds 7 (both active operands), R2 is 0 (will hold the result). The PC holds 108 (address of next instruction). IR holds the current instruction encoding. Flags hold status bits.
Worked example

Tracking register state through three instructions.

Initial state: R0 = 0, R1 = 0, R2 = 0, PC = 100.

Memory (values stored there):

  • Address 200: value 25
  • Address 201: value 17

Instruction at address 100: LOAD R0, 200

  • Execute: read memory address 200, get 25. Store 25 in R0.
  • After: R0 = 25, R1 = 0, R2 = 0, PC = 104.

Instruction at address 104: LOAD R1, 201

  • Execute: read memory address 201, get 17. Store 17 in R1.
  • After: R0 = 25, R1 = 17, R2 = 0, PC = 108.

Instruction at address 108: ADD R2, R0, R1

  • Execute: ALU computes 25 + 17 = 42. Store 42 in R2.
  • After: R0 = 25, R1 = 17, R2 = 42, PC = 112.

Observation: throughout all three cycles, the program counter was also changing — 100 → 104 → 108 → 112. It is the register that drives the fetch step. Every other register changed only when a specific instruction targeted it.

Practice 0 / 5

Accessing a register takes roughly 1–2 clock cycles. Accessing RAM takes roughly 100–300 clock cycles. How many times faster is a register access than a RAM access (use the lower bound)? Type the number.

An x86-64 CPU has how many general-purpose 64-bit registers? Type the number.

Each general-purpose register on a 64-bit CPU holds how many bits? Type the number.

Which special-purpose register holds the address of the next instruction to fetch? Type 1 (program counter) or 2 (flags register).

After LOAD R0, 200 executes, where does the value from memory address 200 end up? Type 1 (in register R0) or 2 (in register R1).

Check yourself
Quiz

Why does the CPU keep working values in registers rather than reading and writing main memory for every computation?

Recap

A register is an ultra-fast, named storage slot physically inside the CPU chip. Unlike main memory (RAM), registers are not addressed with a memory address — they are named directly in instruction encodings (R0, R1, RAX, etc.). Registers are 100–300× faster than RAM because they sit on the same silicon as the ALU. The CPU does its actual work — arithmetic, logic, address computation — on values held in registers, not on values in memory directly. A general-purpose register (GPR) can hold any value at any time; which register holds which value is decided by the compiler. Special-purpose registers have fixed hardware roles: the program counter holds the address of the next instruction, the stack pointer tracks the call stack, and the flags register records operation outcomes. Crucially, the program counter is itself a register — the instruction that advances it is just the normal PC-update that happens every cycle.

Continue the climb ↑Machine code
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.