Test, Then Jump
There's no IF on the 6510. Learn how the machine makes decisions instead — compare a value, which sets a flag, then branch on that flag. Build your own IF, and write your first labels.
You've met everything the machine is. Now: how does it decide?
In BASIC you wrote IF X = 5 THEN …. The 6510 has no IF. It does something smaller and stranger, in two steps:
- Compare.
cmp #5subtracts 5 fromA, throws the answer away, and keeps only the flags — little yes/no bits the last operation leaves behind. IfAwas exactly 5, the result was zero, so the zero flag is set. - Branch.
beq equalmeans "branch to equal if the zero flag is set" (Branch if EQual). If it isn't set, the machine carries straight on.
Test, then branch. You assemble the IF yourself out of those two pieces — and it turns out that's all IF ever was.
What you'll see by the end
A green border — because the program decided on green. We put 5 in A, compared it with 5, and because they matched, the program branched to the road that sets green. Put a different number in and it takes the other road, to red. The colour is the program's answer to a question.
Building the IF
; Meet the Machine - Unit 7: Test, Then Jump
; Assemble with: acme -f cbm -o decide.prg decide.asm
*= $0801
!byte $0c,$08,$0a,$00,$9e,$32,$30,$36,$31,$00,$00,$00
*= $080d
lda #5
cmp #5 ; compare A with 5 — sets the zero flag if equal
beq equal ; jump to 'equal' if the zero flag is set
lda #2 ; (the red road) not equal
sta $d020
jmp hold
equal lda #5 ; (the green road) equal
sta $d020
hold jmp hold
Read it as a fork in the road. cmp #5 asks the question; beq equal takes the green road if the answer is "equal"; otherwise the code falls through to the red road, then jmp hold skips over the green branch so it isn't run by accident. That jmp is the unconditional jump — go there, always, no flag consulted. (It's the same jmp you've used to hold the picture since Unit 1, now doing a second job: skipping past code.)
Labels — and here your assembler starts to matter
equal and hold are labels you named — the first you've written; until now you were only given loop. A label is just a name for a place in the code, so a jump or branch can aim at it. They come with one rule worth meeting head-on, because this is the first place it can bite:
- They're case-sensitive.
equalandEqualare two different labels. Branch to one having defined the other and the assembler stops with "symbol not defined." Pick a spelling and keep it.
Here's the important part, though. Everything you've learned about the machine — registers, the screen, the flags — is universal: it's true of any 6510, assembled by any tool. But how you write labels is a rule of the assembler — the program that turns your text into bytes — not of the chip. We use ACME; a different assembler might handle label case differently, or want a colon after the name (equal:), or mark "local" labels with a leading dot. This is the first time the tool has a say, not just the machine. From here on, when a rule belongs to the assembler and not the 6510, we'll say so.
Assemble and run
acme -f cbm -o decide.prg decide.asm
A is 5, so the border comes up green — the program took the equal road.
Try this: change the answer
Change lda #5 to lda #3, assemble and run: red, because 3 isn't 5 and the program takes the other road. Put it back to 5: green again. You're not changing the question (cmp #5), only the value being asked about — and watching the decision flip.
Try this: branch three ways
One compare can sort a value into less, equal or greater with a second branch:
; Meet the Machine - Unit 7: branch three ways
; Assemble with: acme -f cbm -o three-way.prg three-way.asm
*= $0801
!byte $0c,$08,$0a,$00,$9e,$32,$30,$36,$31,$00,$00,$00
*= $080d
lda #5
cmp #5
bcc less ; carry clear => A was less than 5 (blue)
beq equal ; zero set => A equals 5 (green)
lda #2 ; otherwise => A was greater (red)
sta $d020
jmp hold
less lda #6
sta $d020
jmp hold
equal lda #5
sta $d020
hold jmp hold
bcc less branches when A was less than the value — that's the carry flag, the other half of a comparison: cmp leaves carry clear when A is below the value, set when it's at or above. (We'll meet carry properly in Unit 12; here, just use it.) Change the first lda to 3, 5 and 9 and watch the border go blue, green, red.
If it doesn't work
acmesays a symbol is not defined. A label's spelling doesn't match between where you defined it and where you branch to it — most often a capital letter. Labels are case-sensitive:equal≠Equal.- The border is always the same colour whatever you load. A branch is testing the wrong flag, or the
jmp holdthat skips the green branch is missing, so both roads run. Compare against the listing. - The program runs off and the screen garbles. A label is misplaced so a jump lands in the wrong spot. Check
equalandholdsit exactly where shown.
What you've learnt
There's no IF — you cmp to compare (which sets flags), then beq (or bcc, bne…) to branch on the result or carry straight on; every decision the machine makes is built from test-then-branch.
What's next
Decisions are far more useful when they're about the player. Next — The Machine Can Hear You — we read the joystick: one direction, one bit, and a branch on whether it's pushed. The first time the machine reacts to you.