Skip to content

Computer Architecture

How a conditional jump makes a loop

A loop in a processor ends with a conditional jump: an instruction that loads the program counter with an earlier address if a flag says so, and otherwise lets it carry on. JNZ, "jump if not zero", sends the program back round while the last result wasn't zero and falls through once it is. In hardware it's a single AND: JUMP = (at this address) AND NOT ZERO.

A four-line program

0: LOAD 3 · 1: DEC · 2: JNZ 1 · 3: HALT

Address 1 takes one away and sets ZERO from the result. Address 2 asks one question: is ZERO set? If not, jump to 1. The counter goes 0, 1, 2, 1, 2, 1, 2, then falls through to 3: three laps for a 3. The number of laps is data, not wiring.

When to jump

JNZ sits at address 2, so its line is the decoder's address-2 line, Q1 AND NOT Q0. It may only jump there, and only with ZERO at 0:

JUMP = Q1 AND NOT Q0 AND NOT ZERO

At any other address JUMP is 0, whatever the flag says.

Where to land

From 2 the counter would go on to 3, which is 11; the jump wants 1, which is 01. Compare the two bit by bit. A bit that's 0 in the target gets AND NOT JUMP, a bit that's 1 gets OR JUMP, and a bit that's the same either way is left alone. Here only the 2s bit differs, so its next value is ANDed with NOT JUMP. That rule works for any fixed target.

Live experiment

Round again, or fall through

The program counter runs 0, 1, 2, 3, and at address 2 JNZ 1 asks one question: is ZERO set? With ZERO at 0 it jumps back to 1, lap after lap; raise ZERO and the next visit to 2 falls through to 3. Then feed the jump ZERO instead of NOT ZERO.

Try it yourself: free lesson

“Go round again” is lesson 5 of 6 in Program Peninsula, Computer Architecture World 3. Free with an account. Lessons unlock in order, so you’ll do the 18 before it first.

In assembly

Every while and for loop you write compiles to a conditional branch at the bottom: BNE ("branch if not equal", which tests Z) on ARM, JNZ or JNE on x86, BRNE on the AVR in an Arduino Uno. An if is a conditional jump forwards, skipping code instead of repeating it. The Z80 even folds the decrement and the test into one instruction, DJNZ.

A jump with no condition, JMP, loops for ever. Arduino's loop() runs inside one: after its last line, control jumps back and calls it again.

Why the test comes last

The flag only describes the most recent calculation, so the decrement or compare that sets it has to come right before the branch. Put another arithmetic instruction between them and the branch tests the wrong result. Compilers arrange the loop so the flag-setting instruction is the last one before the jump.

Free lesson

Now build it yourself

Each lesson comes in three short parts: see the idea, try it on a live board, then build it yourself, with quick checks as you go.

Try it yourself: free lesson

“Go round again” is lesson 5 of 6 in Program Peninsula, Computer Architecture World 3. Free with an account. Lessons unlock in order, so you’ll do the 18 before it first.

Or start from the very first lesson, no account needed

Practice questions

Three quick questions from the lessons. Pick an answer to check it.

  1. Question 1 of 3The counter is at address 1 and ZERO is 0. JUMP is…
    Show the answer

    Answer: 0: only address 2 can jump. JUMP is address 2 AND NOT ZERO. At address 1 the address line is 0, so JUMP is 0 whatever the flag says.

    • Why not “1 on every address”? A jump on every address would stop the program ever running in order. JUMP is gated by address 2's line.
    • Why not “1: ZERO is 0”? ZERO at 0 is only half the condition. JUMP also needs the counter at address 2, where JNZ lives.
    • Why not “X”? X means unknown, but every input to JUMP is known here: the address line is 0, so JUMP is 0.
  2. Question 2 of 3A jump target has a 0 in the 2s bit. That bit's D gets…
    Show the answer

    Answer: Its next count AND NOT JUMP. AND NOT JUMP forces the bit to 0 on a jump and leaves the count alone otherwise. A 1 in the target would get OR JUMP.

    • Why not “Its next count OR JUMP”? OR JUMP forces the bit to 1, which is right for a 1 in the target, not a 0.
    • Why not “JUMP”? D = JUMP would set the bit on a jump and clear it on every other tick, so it could never count.
    • Why not “Nothing extra”? With nothing extra, a jump from 2 would go on to 3 like any other count. The 0 has to be forced.
  3. Question 3 of 3With LOAD at 1, the program counter…
    Show the answer

    Answer: Takes the switches' value: a jump. LOAD picks the new address.

    • Why not “Resets”? A reset forces a fixed address, usually 0. LOAD takes whatever address is on its inputs.
    • Why not “Counts on”? It counts on only with LOAD at 0. LOAD at 1 lets the new address through instead.
    • Why not “Holds”? Holding would need the counter to feed its own value back. LOAD replaces it with a new one.
Keep practising: free lesson

“Go round again” is lesson 5 of 6 in Program Peninsula, Computer Architecture World 3. Free with an account. Lessons unlock in order, so you’ll do the 18 before it first.

Questions people ask

What does JNZ mean?

Jump if not zero. It checks the zero flag, set by the last arithmetic or compare instruction, and loads a new address into the program counter only if the flag is clear. On x86, JNE (jump if not equal) is the same instruction under another name.

How does a for loop become machine code?

The compiler keeps the loop counter in a register, lays out the body as a row of instructions, and ends it with a decrement or compare plus a conditional branch back to the top. When the condition fails, the branch falls through to the code after the loop.

Why does a loop need a flag?

The jump has to decide, and all it can look at is a bit the processor already has. The flag describes the last calculation, so whatever the loop tests must be worked out just before the branch, usually by the decrement or the compare.

Every topic