Assembly & the CPU

the program counter / instruction pointer

Imagine reading a recipe with your finger on the line you are about to do. After each step you slide your finger down to the next line. The program counter is the CPU's finger: a special register that holds the address of the next instruction to run. It is what keeps the machine moving forward through the program.

The basic loop is: the CPU reads the instruction at the address in the program counter, advances the program counter to point just past it, then executes the instruction. Because instructions sit one after another in memory, advancing automatically lands on the next one — that is why code runs top to bottom by default. On x86-64 this register is called rip (the instruction pointer); on ARM it is the program counter, pc. A jump or branch instruction works simply by writing a new address into the program counter, so the CPU's finger lands somewhere else; a function call saves the current program counter as a return address and then jumps; a return reads that saved address back into the program counter.

Almost everything about control flow is really just the program counter changing. An if that skips a block is a conditional jump that may or may not overwrite the program counter; a loop is a jump backward to an earlier address; calling and returning from a function is saving and restoring it. You rarely manipulate it directly in C, but understanding that it exists demystifies how a flat list of instructions can branch, loop, and call subroutines.

If the program counter holds 0x401000 and the instruction there is 4 bytes long, after the fetch it becomes 0x401004 — unless a jump writes a different address into it.

The program counter always points at the next instruction; branching is just changing what it points to.

The program counter is advanced before the current instruction finishes executing, so it already points at the next instruction; a relative call or branch is computed against this 'next' address, not the address of the instruction itself — a detail that trips up people first reading disassembly.

Also called
PCinstruction pointerIPrip指令指標