Base CS from zero
Loops as repeated jumps
You know that a jump instruction can set the program counter to any address — including an address earlier in memory than the current instruction. What happens if the CPU jumps backward to an instruction it already ran?
It runs that instruction again. And if the next instruction is again a jump backward, it runs it a third time. And a fourth. And keeps going until something changes.
That repetition is a loop. Not a special hardware feature — the CPU has no concept of “loop”. It is just the same fetch–decode–execute cycle running the same instructions repeatedly, driven by a conditional jump that keeps pointing the program counter backward until a condition fails.
Every while loop, every for loop, every repetition in every program reduces to this
one mechanism. When you understand the backward jump, you understand loops at the level
the machine sees them.
After this lesson you can explain a loop as a backward jump driven by a condition, trace the machine-level steps of a while loop, describe why while and for have the same underlying structure, and explain precisely why an infinite loop occurs.
The backward jump: revisiting an earlier instruction. A jump instruction can target any address — forward or backward in memory. A backward jump sets the program counter to an address that is smaller than the address of the jump instruction itself. The next fetch comes from that earlier address, and the CPU re-executes everything between that address and the jump.
Nothing about a backward jump is special to the CPU hardware. It is the same JUMP opcode as a forward jump. The only difference is the magnitude and direction of the target offset: negative offset = backward, positive offset = forward. The CPU simply sets the PC to the target address and resumes its loop.
What makes a backward jump useful is pairing it with a conditional test. If you jump backward unconditionally, you have an infinite loop immediately. If you jump backward only when a condition holds, you have a controlled repetition — the body runs again only as long as the condition remains true.
The shape of a while loop in machine code. A while (condition) { body } compiles
to the following machine-level structure:
[LOOP_TOP: CMP ...] ; test the condition
[conditional jump to LOOP_END] ; exit if condition is FALSE
[body instructions] ; the loop body
[unconditional JUMP to LOOP_TOP] ; jump BACKWARD to the test
[LOOP_END: ...] ; continues here after the loopThe key insight: the test comes first, before the body. On every iteration, the CPU:
- Evaluates the condition with a compare instruction, updating the flags.
- Checks the flag with a conditional jump — if the condition is false, the jump is taken and the CPU exits the loop (forward jump to LOOP_END). If the condition is true, the jump is not taken (fall-through).
- Executes the loop body.
- Reaches the unconditional backward jump and sets the PC back to LOOP_TOP.
- Returns to step 1.
The backward jump at the bottom of the loop is always unconditional. All the decision logic lives in the conditional jump at the top.
Why this works
Why is the condition tested at the top? Because while (condition) must not execute
the body at all if the condition is already false when the loop is first reached. Testing
at the top ensures the body runs zero times when the condition starts false. This is
different from a do { body } while (condition) loop, where the body always runs at
least once because the test is at the bottom. At the machine level, the only difference
is whether the CMP + conditional jump pair is placed before or after the body instructions.
The shape of a for loop: same machine code, different source syntax. A for (init; condition; update) { body } is syntactic sugar — a source-level convenience. When
compiled, it becomes the same backward-jump structure as a while loop:
[init instructions] ; runs once before the loop starts
[LOOP_TOP: CMP ... condition ...]
[conditional jump to LOOP_END]
[body instructions]
[update instructions] ; increment/decrement at the bottom
[unconditional JUMP to LOOP_TOP]
[LOOP_END: ...]The init code runs once before the first iteration. The update code runs at the bottom of
each iteration, just before the backward jump. The test and the backward jump are in
exactly the same positions as in a while loop. At the machine level, the CPU cannot
distinguish a compiled while from a compiled for — they produce the same pattern of
instructions.
Infinite loops: when the backward jump never stops. A loop runs forever when the condition tested before each backward jump never becomes false. There are two reasons this can happen:
-
Unconditional backward jump: the “loop” has no condition at all — the jump at the bottom always fires, the PC is always reset to the top, and the CPU never escapes. This is
while (true)compiled to a plain JUMP (no CMP, no conditional), which is intentional in server loops and event loops. -
Condition that never becomes false: the test exists but the loop body never changes the values being compared, so the condition remains true forever. For example, if a loop counts down from 10 but a bug in the body prevents the counter from decrementing, the CMP always sees the same value, the flag stays the same, and the backward jump always fires.
An infinite loop is not a hardware fault. The CPU is doing exactly what the program tells it: running the backward jump, resetting the PC, running the body, and jumping backward again, indefinitely. The CPU will continue until the OS or an interrupt stops it.
Tracing a simple countdown loop.
Program: count down from 3 to 0, stopping when the counter reaches 0.
Address Instruction Effect
100 LOAD R0, 200 R0 ← counter value (starts at 3)
104 CMP R0, 0 compare R0 with 0, update Z and N flags
108 JE 120 jump to 120 (exit) if Z=1 (R0 == 0)
112 SUB R0, 1 R0 ← R0 − 1
116 JUMP 104 backward jump to the test at 104
120 ... loop is done; continues hereIteration 1 (R0 = 3):
- CMP at 104: 3 − 0 = 3. Z = 0, N = 0. PC → 108.
- JE at 108: Z = 0, condition “equal” is false. Fall through. PC → 112.
- SUB at 112: R0 = 3 − 1 = 2. PC → 116.
- JUMP at 116: backward jump. PC ← 104.
Iteration 2 (R0 = 2):
- CMP at 104: 2 − 0 = 2. Z = 0. PC → 108.
- JE at 108: Z = 0, fall through. PC → 112.
- SUB at 112: R0 = 2 − 1 = 1. PC → 116.
- JUMP at 116: PC ← 104.
Iteration 3 (R0 = 1):
- CMP at 104: 1 − 0 = 1. Z = 0. PC → 108.
- JE at 108: Z = 0, fall through. PC → 112.
- SUB at 112: R0 = 1 − 1 = 0. PC → 116.
- JUMP at 116: PC ← 104.
Iteration 4 (R0 = 0 — exit condition):
- CMP at 104: 0 − 0 = 0. Z = 1. PC → 108.
- JE at 108: Z = 1, condition “equal” is true. Jump. PC ← 120.
- Loop exits. R0 = 0.
The body ran exactly 3 times. The backward jump at 116 fired 3 times. On the 4th test, the Z flag finally became 1 and the conditional jump escaped the loop.
Common mistake
A common misconception is that a loop “knows how many times it will run”. The CPU does not know. On each iteration, the CPU tests the condition, sees a flag value, and makes a single binary decision (jump or fall through). It has no memory of how many times it has already jumped backward. The iteration count emerges from how many times the condition was tested and found true — the CPU counts nothing; only the condition changing is what terminates the loop.
A backward jump sets the PC to an address that is smaller than the jump instruction's address. After a backward jump from address 120 to address 100, what is the PC?
In a while loop compiled to machine code, where is the CMP instruction placed relative to the loop body?
A while loop with a counter starting at 5, decrementing by 1 each iteration, stopping when counter reaches 0. How many times does the backward jump execute?
In machine code, is there a hardware difference between a while loop and a for loop?
A loop has no compare instruction — only an unconditional JUMP back to the top. How many iterations does it run?
What is the machine-level mechanism that makes a while loop repeat its body?
A loop is a backward jump — a jump instruction whose target address is earlier in
memory than the instruction itself. Combined with a conditional test, the backward jump
creates controlled repetition: the loop body executes, the condition is re-evaluated, and
if the condition is still true the PC is reset to the top of the loop; if false, a
conditional jump exits the loop by jumping forward past the body. A while loop places
the condition test before the body; a for loop adds an init block before the loop and
an update block before the backward jump, but the underlying machine pattern is identical.
An infinite loop occurs when the backward jump is unconditional or when the condition
tested before each iteration never becomes false — the CPU cannot detect or prevent this;
it continues the backward-jump cycle indefinitely until the OS or an interrupt intervenes.