A promise written in stone
In the foundations rung we drew the great seam between software and hardware and named the layer that lives there: the instruction set architecture, or ISA. This rung opens that layer up. Think of the ISA as a contract with two signatures. On one side, every compiler and assembly programmer promises to speak only in the instructions on the list. On the other, every chip that claims to implement the ISA promises to obey those instructions exactly as written. As long as both keep their word, a program need never know which particular chip it runs on, and a chip need never know which program it runs.
This is the hardware/software interface, and it is deliberately the most conservative thing in the whole machine. Microarchitectures are reinvented every year or two; the ISA is meant to last decades. The reason is binary compatibility: a program compiled in 1995 should still run on a 2025 chip of the same family, because the contract it was built against has not changed. Break the ISA and you strand every program already written for it. So architects guard it jealously, adding to it far more often than they ever change it.
What's actually in the contract
A contract this important needs only a surprisingly short list of clauses. The ISA names a small set of fast scratchpad locations called architectural registers — the named slots a program is allowed to talk about by name. It names a special register, the program counter, that always holds the address of the next instruction to run. It defines a kind of instruction for each thing a program needs to do: do arithmetic, move data to and from memory, and decide what to run next. And it spells out exactly how each instruction is written down as a pattern of bits. That is essentially the whole document.
Throughout this rung we'll use RISC-V as our example, because it is a clean, modern, open standard with nothing to hide — no decades of historical baggage glued on. Those three instruction families above are exactly its backbone. Arithmetic instructions like add and shift compute on values already sitting in registers. Load and store instructions are the only instructions that touch memory — a load copies a word from memory into a register, a store copies the other way. And control-flow instructions — branches and jumps — change the program counter so the machine runs something other than the very next instruction. Everything a CPU does is some weave of these three threads.
# A tiny RISC-V snippet: add 10 to a value in memory, store it back. # x10, x11 are architectural registers. 0(x10) means address in x10. lw x11, 0(x10) # LOAD: x11 <- memory[x10] addi x11, x11, 10 # ARITH: x11 <- x11 + 10 (10 is an immediate) sw x11, 0(x10) # STORE: memory[x10] <- x11 bne x11, x0, loop # BRANCH: if x11 != 0, set PC to 'loop'
How an instruction becomes bits
Because of the stored-program idea, an instruction is itself just a number in memory. The ISA fixes the instruction format — the rulebook for carving a fixed-width word into fields. In RISC-V a typical instruction is 32 bits split into a few named slots. One field, the opcode, says which operation this is. Other fields name the source and destination registers by number. And a remaining field can hold a small constant baked right into the instruction, called an immediate operand — that is where the 10 in our addi lived.
Why fixed-width, equally-sized fields? Speed of decoding. When every instruction is the same length and the register fields always sit in the same bit positions, the hardware can begin reading registers before it has even finished figuring out the opcode. That regularity is a deliberate gift from the architecture to the microarchitecture. We'll dismantle these formats bit by bit — and trace the sign-extension trick that lets a short immediate stand in for a full-width number — in guide 3.
Reaching memory: addressing and the load-store idea
An instruction must say where in memory to read or write, and the ISA's menu of ways to compute that location is its set of addressing modes. RISC-V keeps this list short on purpose. The everyday mode is base-plus-offset: take an address sitting in a register and add a small constant, exactly as 0(x10) meant "the address in x10, plus offset 0". A branch uses a similar trick on the program counter — add an offset to where we are now to decide where to jump. A handful of simple, predictable modes is far easier for hardware to decode quickly than a sprawling zoo of exotic ones.
This restraint reflects a defining design choice called a load-store architecture. The rule is blunt: arithmetic instructions may operate only on registers, never directly on memory. If you want to add a number that lives in memory, you must first load it into a register, do the math, and store the result back — exactly the three-line dance in our snippet. This separation keeps the common arithmetic instructions short and fast, and confines every slow memory access to two clearly-marked instruction kinds. We'll explore addressing modes and this load-store discipline thoroughly in guide 4.
The memory model the ISA exposes
The ISA also paints the program a picture of memory, and the picture is reassuringly simple: one long, flat array of bytes, each with its own numeric address, from zero up to the largest address the word size allows. A 32-bit machine can name 2^32 distinct byte addresses (about 4 gigabytes); a 64-bit machine names 2^64, an almost unimaginable range. This flat byte-addressed array is the memory model every load and store talks to. The program is encouraged to believe this whole array belongs to it alone.
That belief is a beautiful fiction. Later rungs reveal that virtual memory quietly translates each program's private addresses onto the real, shared chip — every program thinks it owns the whole house while a translator maps its rooms to the actual building. The ISA's memory model is the simple promise; the model also has to say harder things, like which byte of a multi-byte number comes first (endianness) and what one core sees when another core writes (the consistency model). For now, hold the clean picture: a flat array of addressable bytes that loads read and stores write.
RISC vs CISC, honestly
You will hear ISAs sorted into two camps. A RISC (reduced instruction set computer) like RISC-V keeps a small set of simple, fixed-length, load-store instructions — the lean, regular style we've described. A CISC (complex instruction set computer) like x86 grew a large set of powerful, variable-length instructions, some of which do several things at once, including reading from memory, computing, and writing back in a single instruction. The old story was a clean rivalry: RISC simple and fast, CISC rich but slow. The truth is far more interesting.
Modern x86 chips blurred the line almost out of existence. Inside, the processor does not execute its complex instructions directly. A decoder cracks each complex instruction into a handful of small, RISC-like micro-ops, and the fast engine underneath runs those micro-ops — pipelined, out of order, just like a RISC core. So the visible CISC contract is honored on the surface while the hidden microarchitecture is essentially RISC. The debate is no longer RISC-versus-CISC hardware; it is mostly about the encoding of the instruction stream, which still affects how easy and power-efficient decoding is.