Sega CD Development

Home Sega CD SLO 32X Transfer ConvSCD

Part IV: Branches, Conditions and Labels

So far you can add, subtract, and shove data around. In and of itself this isn't too useful. The program will always do the exact same thing and has no real way to make decisions based on input. With this lesson that will change.

Remember that in a previous lesson, I said that the Program Counter is a special address register that points to the current instruction and that this register can't be changed directly. Today, I'm going to show you two instructions that can change PC, jmp and bra.

The jmp instruction replaces the value in PC with another address. This can be accomplished using any of the addressing modes except for ordinary PC relative addressing and register direct addressing.

Examples:
jmp $FF0000 ;this would cause a jump to memory address$FF0000

jmp $F000.w ;this would cause a jump to memory address $FFF000

movea.l #$300, a0
jmp (a0) ;this would cause a jump to memory address $300

move.w #$40, d0
jmp $4(d0, PC) ;this would cause a jump to $44 bytes past the current PC

The bra instruction is similar to jmp, except that it only works with simple PC relative addressing.

Examples:
bra #$100 ;branches to $100 bytes past the current pc
bra #$6.b ;brances to $6 bytes past the current pc

Having to calculate memory addresses and offsets are a real pain so assembler authors came up with a simple way around all this nonsense. They're called labels. A label is simply an alphanumeric string without any spaces. It must start with a letter. To define a label simply type it in at the first position on a line and add a colon. Once you've defined a label, you can treat it like a normal address. Also note, that instructions need to have whitespace in front of them, unlike what I've done so far in the tutorial

Example:
Mylabel:
bra Mylabel ;this would stick the processor in a never ending loop

Don't do this:
Mylabel:
bra Mylabel

Now you know how to make programs that don't just go in a straight line, but there is something that makes this even more useful, flags and conditions. The flags are just a bunch of bits in a special register called the Condition Code Register or CCR for short. These bits are effected by most instructions. For this section of the tutorial I'm only going to introduce you to one flag, the zero flag. This flag is set to 1 (true) if the result of the last operation was zero or more accurately if the destination in the last operation was set to zero.

Examples of when the zero flag is set:
move.w #0, d0

move.w #1, d0
sub.w #1, d0

move.b #$FF, d0
add.b #1, d0

Examples of when the zero flag is not set:
move.w #1, d0

move.w #3, d0
sub.w #1, d0

move.b #$FF, d0
add.b #$2, d0

Well that's all well and good, but how do we use these flags once they've been set? Simple, with branch instructions. Remember bra? That stands for BRanch Always. There are a number of variations on bra that only branch when certain flags are set. I'm going to introduce you to two right now, beq and bne.

beq stands for Branch if EQual. What this really means is that the processor will take the branch if the zero flag is set. If not, then execution continues as normal. You may be wondering where the EQual part comes from. It makes sense in subtraction and compare(we haven't touched on compare yet) operations. If both values are equal and you perform one of these operations, then the result will be zero, thus the name of the instruction.

Example of branch getting taken:
move.w #1, d0
sub.w #1, d0 ;1-1 = 0, zero flag set to 1 (true)
beq Skip: ;zero flag is set so the branch is taken

move.w #5, d0 ;this instruction is skipped

Skip: ;executiong jumps to here
addq #3, d0 ;d0 now equals 3

Example of branch not getting taken:
move.w #2, d0
sub.w #1, d0 ;2-1 = 1, zero flag set to 0 (false)
beq Skip: ;branch is not taken

move.w #5, d0 ;this instruction is executed

Skip:
addq #3, d0 ;d0 now equals 8

bne stands for Branch if Not Equal. It's the exact opposite of beq. If the zero flag is zero (false) than the branch is taken otherwise execution continues as normal. I won't do an example, since it should be easy enough to figure out given the examples for beq.


Part III Sega CD Home Part V