JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Instructions, Registers, and the Program Counter

Open the contract and look at its moving parts: the tiny club of registers a program names by hand, the one pointer that always knows what runs next, and the loop that fetches, decodes, and executes a program one number at a time.

Registers: the desk you keep your work on

Guide 1 named the parts of the contract; now we pick them up and turn them over. Start with the workspace. Memory is enormous but far away — every access is a long walk to the library. So the ISA gives a program a tiny, intimate set of fast slots it can name directly: the architectural registers. RISC-V hands you 32 of them, each holding one machine word, called x0 through x31. They are your desk: a place to keep the handful of values you are actively working on, right under your hand, so you rarely have to walk to the shelves.

Why so few? Speed costs scarcity. A register must be reachable in a single fast tick, and the more of them there are, the more bits each instruction must spend just to name one, and the slower the storage gets. So the ISA settles on a small, named club — a register file the hardware can read two values from and write one value to all within one cycle. Notice the word architectural: these are the registers the contract promises by name. The chip underneath may secretly own dozens more (we will meet register renaming in a far later rung), but a program may only ever speak of these 32.

The program counter: the finger on the page

Among all the registers, one does a job nothing else can: the program counter, or PC. Because of the stored-program idea from the foundations rung, the instructions of a program are themselves just numbers sitting in memory, one after another. Something has to remember where in that list we are right now. That something is the PC — a register holding the address of the instruction about to run. Picture it as a finger pressed on the line of a book you are reading aloud: it marks the exact spot, and nothing gets read until the finger points at it.

By default the finger slides forward by one instruction's width each step — in RISC-V, by 4 bytes, since instructions are 4 bytes long — so execution flows straight down the page. The entire purpose of control-flow instructions is to move that finger somewhere other than the next line. A conditional branch tests something — is this register zero? is one less than another? — and, if the test passes, sets the PC to a different address, the branch target. A jump moves it unconditionally. Loops, if-statements, and function calls are all, underneath, just disciplined ways of shoving the program counter around.

The fetch-decode-execute loop

Registers and the PC come alive inside one relentless loop — the instruction cycle, the heartbeat of every processor. It is astonishingly simple, and the machine does nothing else, billions of times a second, for as long as it is on. Each turn of the loop reads the instruction the PC points at, works out what it means, carries it out, and advances the PC so the next turn reads the next instruction. The same four moves, over and over, are enough to run every program ever written.

  1. Fetch: read the instruction word stored at the address in the program counter, copying it out of memory into the processor.
  2. Decode: pick the instruction apart into its fields — which operation, which registers, which immediate — so the control logic knows what to set up.
  3. Execute: do the actual work — add in the ALU, compute a memory address, or test a branch condition.
  4. Write back and advance: store any result into the destination register, then update the PC — by 4 for the next instruction, or to a branch target if control flow demanded it.

A tiny program, traced by hand

Let us watch the registers and the PC actually move. Here is the inner loop of summing the first n numbers: keep a running total in one register, count down in another, and branch back until the counter hits zero. Read it not as text but as a tiny machine in motion — each line is one turn of the cycle, the PC sliding down by 4 each time, except where the branch flicks it back up to the top.

# sum = 0; while (i != 0) { sum += i; i -= 1; }
# x5 = sum (total), x6 = i (counter). Assume x6 already holds n.

  addi  x5, x0, 0      # x5 <- 0            sum starts at zero (x0 is the zero reg)
loop:                                       # PC value of this line is the branch target
  add   x5, x5, x6     # x5 <- x5 + x6      add current i into the total
  addi  x6, x6, -1     # x6 <- x6 - 1       count down by one
  bne   x6, x0, loop   # if x6 != 0, PC <- loop      ...else fall through (PC += 4)

# Trace with n = 3:  add->5, dec->2, branch taken;  add->7? no: x5=3 then 5 then 6...
# i=3: sum 0->3   i=2: sum 3->5   i=1: sum 5->6   i=0: branch NOT taken, loop ends.
Three registers and the PC are the whole story. Arithmetic stays in registers; the bne steers the program counter; x0 supplies a free zero. No memory is touched at all.

Notice what is not here: not one load or store. Because RISC-V is a load-store architecture, arithmetic instructions like add and addi may compute only on registers. The moment a value lived in memory instead, we would need a load to fetch it into a register before any math and a store to put a result back — the only two instruction kinds allowed to cross the gap to memory. That discipline is exactly why the inner loop above is so fast: it never leaves the desk for the library.

What the ISA hides, and what it must not

The registers, the program counter, and the cycle are the part of the machine the contract makes visible — the state a program is allowed to name and reason about. Everything else is hidden on purpose. A program cannot see the caches, the pipeline depth, or how many instructions are secretly in flight; it sees only registers changing and memory changing, in the order the contract promises. That hidden freedom is what lets one ISA outlive many chips: the organization underneath — the how — is reinvented while the visible state — the what — stays put.

But there is a line the chip must never cross, however cleverly it overlaps and reorders work underneath. The result a program observes — the final values in its registers and memory — must be exactly what running each instruction one at a time, strictly in PC order, would have produced. A pipeline may juggle five instructions and an out-of-order engine may start whichever is ready first, like a kitchen cooking whichever order's ingredients arrive soonest; yet both still commit their results in the original order, plating each dish in the sequence it was ordered. The contract guarantees the sequential illusion. How the hardware keeps that promise while running fast is the whole drama of the rungs ahead.