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.
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
Bccinstruction —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
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
moveand thecmpdon't match.cmp.w #5,d0asks "isd0equal to 5?" — setd0to 5 to get the equal branch. - Both colours seem to fight. A missing
bra .showlets the code fall through into the.equalline after the red path. The unconditional branch is what skips the else. - It won't assemble — "undefined symbol". A branch target like
.equalmust 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.