Skip to content
Game 0 Unit 8 of 19 1 hr learning time

Test, Then Branch

A program that can't make a decision can't do much. The 68000 has no IF — instead you compare two values, which sets the flags, then branch on a flag. That pair, CMP and Bcc, is every IF you'll ever write.

42% of Meet The Machine

So far the code has run in a straight line — one instruction after the next, top to bottom. Real programs fork: if this, do that; otherwise, do the other thing. That's where we turn now.

The 68000 has no IF instruction. A decision is two steps:

  • Compare two values with CMP. This sets the flags — a handful of bits inside the processor that remember how the last sum came out: was the result zero, was it negative, did it carry.
  • Branch on a flag with a Bcc instruction — BEQ (branch if equal), BNE (if not equal), BLT, BGT, and the rest. The branch either jumps somewhere else or falls through to the next instruction.

CMP then Bcc is the IF you build by hand. Get this pair and you have every conditional in every program ever written.

What you'll see by the end

The Amiga screen filled with solid green.
Green — the colour the equal branch chose. Change the comparison and the other branch paints red instead.

A green screen. The code compares a value against 5, finds they match, and takes the branch that loads green. The red path is right there in the code, one branch away — it just wasn't taken this time.

Compare, then branch

;──────────────────────────────────────────────────────────────
; Meet the Machine (Amiga) - Unit 8: Test, Then Branch
;
; There is no IF. You COMPARE two values - which sets the flags - then BRANCH on
; a flag. The YOUR CODE block decides which colour ends up in the slot.
;──────────────────────────────────────────────────────────────

CUSTOM      equ $dff000
DMACON      equ $096
INTENA      equ $09a
INTREQ      equ $09c
COP1LC      equ $080
COPJMP1     equ $088
BPLCON0     equ $100
COLOR00     equ $180

            section code,code_c

start:
            lea     CUSTOM,a5
            move.w  #$7fff,INTENA(a5)
            move.w  #$7fff,INTREQ(a5)
            move.w  #$7fff,DMACON(a5)
            lea     copperlist,a0
            move.l  a0,COP1LC(a5)
            move.w  d0,COPJMP1(a5)
            move.w  #$8280,DMACON(a5)

            ; ----------------------------------------------- YOUR CODE START
            move.w  #5,d0               ; the value we'll ask about
            cmp.w   #5,d0               ; compare it with 5 - sets the flags
            beq     .equal              ; branch if equal
            move.w  #$0f00,colourval    ; not equal: red
            bra     .show
.equal:
            move.w  #$00f0,colourval    ; equal: green
.show:
            ; ------------------------------------------------- YOUR CODE END

forever:
            bra.s   forever

copperlist:
            dc.w    BPLCON0,$0200
            dc.w    COLOR00
colourval:
            dc.w    $0000
            dc.w    $ffff,$fffe

The decision lives in five lines:

move.w  #5,d0               ; the value we'll ask about
cmp.w   #5,d0               ; compare it with 5 - sets the flags
beq     .equal              ; branch if equal
move.w  #$0f00,colourval    ; not equal: red
bra     .show
.equal:
move.w  #$00f0,colourval    ; equal: green

cmp.w #5,d0 subtracts 5 from d0 but throws the answer away — it keeps only the flags. Since d0 holds 5, the result is zero, so the zero flag is set. beq means "branch if that zero flag is set," so it jumps to .equal and loads green.

The bra .show matters: without it, the code would fall straight through the .equal line and run both colours. bra is an unconditional branch — it always jumps — and here it skips the green line when the red path has already run. That "jump over the else" is the shape of every if/else you'll write.

The colour still reaches the screen the same way as before: you write it into the Copper's colourval slot, and the Copper shows it.

Assemble, master, and run

make

A green screen — the equal branch won.

Try this: take the other path

Change the first line to move.w #7,d0. Now d0 holds 7, the compare with 5 is not equal, the zero flag stays clear, beq doesn't branch — and the code falls through to the red line. Reassemble and the screen turns red. You've walked the other side of the fork.

Try this: a different question

Swap beq for bne (branch if not equal) and put d0 back to 5. Same values, opposite question — and the opposite branch is taken. The flags don't change; only which one you ask about does.

If it doesn't work

  • The screen is red when you expected green. The two values in the move and the cmp don't match. cmp.w #5,d0 asks "is d0 equal to 5?" — set d0 to 5 to get the equal branch.
  • Both colours seem to fight. A missing bra .show lets the code fall through into the .equal line after the red path. The unconditional branch is what skips the else.
  • It won't assemble — "undefined symbol". A branch target like .equal must appear as a label, spelt the same, with a colon, somewhere in the code.

What you've learnt

The 68000 makes a decision in two moves: CMP compares two values and sets the flags, then a Bcc branch (BEQ, BNE, and the rest) jumps or falls through based on a flag. An unconditional BRA skips the path not taken. That's the IF — and the IF/ELSE — assembled by hand.

What's next

A decision made once is a start; a decision made every frame is a game. Next — The Vertical Blank — we wait for the screen to finish drawing, fifty times a second, and do one small job each time. That heartbeat is the loop every game runs inside.