A CPU register is a tiny piece of storage built directly into the processor, holding a single value, typically the width of the machine’s word, such as 32 or 64 bits. Registers are the fastest storage a computer has, far faster than main memory, because they sit inside the execution core where arithmetic and logic happen. When a processor adds two numbers, those numbers are almost always in registers, and the result lands in a register too. Memory, by comparison, is distant; moving data between memory and registers is one of the most common things a program does.
Registers fall into a few kinds. General-purpose registers hold the operands and intermediate results of ordinary computation and can be used fairly freely by program code. Special-purpose registers have fixed roles: the program counter (or instruction pointer) holds the address of the next instruction to execute, and the stack pointer tracks the top of the call stack. A flags or status register holds individual bits set as side effects of operations, such as whether the last result was zero, negative, or produced a carry; conditional branches read these flags to decide which way to go. Together these registers form the architectural state the processor carries from one instruction to the next.
The exact set of registers is part of a processor’s architecture and is spelled out in the vendor’s manual. Intel’s “Intel 64 and IA-32 Architectures Software Developer’s Manual,” whose first volume “describes the architecture and programming environment of processors supporting IA-32 and Intel 64 architectures,” lays out the general-purpose registers, the EFLAGS/RFLAGS status register, and the instruction pointer that define the visible state of an x86 processor. Other architectures publish their own: ARM’s AArch64 defines thirty-one general-purpose registers plus a dedicated program counter and stack pointer, and RISC-V specifies its own register file in its base specification. The conceptual roles are similar even when the counts and names differ.
The collection of a processor’s registers is often called the register file, and its small size is deliberate. Registers are expensive: each one is fast circuitry tightly coupled to the execution units, so there can only be a handful. This scarcity shapes how programs are compiled. A compiler performs register allocation, deciding which variables live in registers at each moment and which must be spilled back to memory, because there are never enough registers to hold everything at once. Good register allocation is one of the larger sources of performance in optimized code.
Registers also sit at the center of agreements between separately compiled pieces of software. A calling convention dictates which registers carry function arguments, which hold return values, and which a called function must leave untouched, precisely because registers are the shared, fast scratch space that code passes through. Understanding registers is therefore foundational: they are where computation actually occurs, the state that a context switch must save and restore, and the resource around which much of low-level performance is organized.