Branching and Loops

Code always runs strictly from top to bottom. But any game is made of loops and conditions: if the snake ate an apple — grow the tail, otherwise — just keep crawling. How do you break this straight path?

That's what jump instructions are for — they're like teleports for the Program Counter. We built the program counter in a separate article; now let's see how to control it from a program.

The Ershov Computer has three jump instructions: JMP, JZ, and JN. They're what turns linear code into a game.

The unconditional jump: JMP

When the processor hits a JMP, it simply forgets where it was and teleports to the line of code it was told. That's how an endless game loop is born — the loop that makes the game run frame after frame, always returning to the beginning.

JMP checks no conditions at all — it's a pure teleport. We'll leave conditions to its siblings.

Conditional jumps: JZ and JN

Conditional jumps are far more interesting: JZ (jump if Zero) and JN (jump if Negative). They work together with the ALU flags: the processor looks at a flag — if the condition holds, the teleport fires and the program follows one branch; if not, the teleport is ignored and execution continues straight ahead.

InstructionOpcodeConditionExample from the game
JMP7Alwaysthe endless game loop
JZ8Zero flag = 1lives run out → Game Over
JN12Negative flag = 1coordinate negative → off the field

This is the hardware foundation of if / else statements, without which no program can survive.

How a jump works in hardware

The formula is simple: PC.Load = JumpUncond OR (JumpCond AND flag). An unconditional jump (JumpUncond) loads the address always. A conditional one — only when the decoder's JumpCond signal matches an ALU flag (Zero or Negative).

If PC.Load = 1, the program counter loads the jump address from the operand instead of incrementing (PC + step). If PC.Load = 0, execution continues in order. One signal, one formula, two sources of decisions.

Where does the jump address come from? From the second byte of the instruction — its operand. In word format a JMP takes two bytes: the opcode and the address to jump to. While the PC steps by +2 through the program, the PC.Load signal replaces the next address with the value from the operand — and the flow of execution leaves the straight path.

The Snake game loop

The heart of any game is its main loop. A simplified skeleton looks like this:

loop:
LDA 0        ; Acc = 0
ADD 254      ; read the gamepad (port 254)
; ... update position, check for collision
JZ game_over ; collision? then game over
STA 255      ; draw a pixel (port 255)
JMP loop     ; and again — next frame
game_over:
HLT          ; stop

These few instructions run dozens of times per second, creating the illusion of motion: every frame is one full pass of the program counter through the loop. JMP closes the iterations, while conditional jumps catch the special cases. For the snake's tail and working with arrays, the index register comes in handy — see the article about pointers.

Lives counter, in numbers

The "game over" condition is checked like this. A lives counter sits in memory: 3. Each death subtracts one: 3 → 2 → 1 → 0. When the result hits zero, the Zero flag is 1, and the JZ instruction sends the program to the game_over label. As long as the counter is above zero, JZ stays silent and the loop continues.

Step by step: 1) the program reads the counter from memory: LDA 0 clears the accumulator, then ADD N adds the value of cell N (LDA can only load numbers); 2) SUB M subtracts the one that was stored in cell M beforehand (in this computer SUB subtracts the contents of a cell); 3) the ALU updates the flags; 4) JZ checks the Zero flag; 5) Zero = 1 — jump to game_over, Zero = 0 — return to the loop.

Common mistakes

1. Forgetting the JMP at the end of the loop: the loop runs once, and the program goes on reading garbage from ROM.

2. Placing the condition calculation after JZ: the jump watches the most recent ALU result.

3. Confusing JMP with JZ: an unconditional jump doesn't read flags at all.

Summary

1. JMP is the unconditional teleport of the program counter (opcode 7).

2. JZ jumps when the Zero flag is 1; JN when the Negative flag is 1.

3. The hardware: PC.Load = JumpUncond OR (JumpCond AND flag).

4. When PC.Load = 1 the program counter loads the address from the operand instead of PC + step.

5. The game loop: read the gamepad → update state → draw a frame → JMP back to the start.

In level 2.28 you will write a program with a loop for a moving dot, and in level 2.29 — a full-fledged Snake game.

Try it in the simulator →