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
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:
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.
“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.
“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 neededPractice questions
Three quick questions from the lessons. Pick an answer to check it.
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.
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.
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.
“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.
Related topics
- What does the program counter do in a CPU?The register that says which instruction comes next, and how jumps make loops.
- What are CPU flags? Zero, carry and the status registerOne-bit facts about the last answer, like zero or too big, that the next instruction uses to decide.
- The fetch-decode-execute cycle explainedFetch an instruction, decode it, carry it out, repeat: how every CPU runs.
- How a countdown circuit counts down and stops at zeroLoad a number, take one away each tick, and let a zero flag stop the count by itself.