As you may remember when data is MOVED into a register or memory address, certain condition codes are set or unset. These codes can be used, along with the results of a CMP instruction and/or the discussion of signed and unsigned numbers above, to determine program flow. To change the flow, we use the branch instruction also known as Bcc or Branch on condition code. The genral format of a Bcc instruction is :
Bcc label
The label part defines where the branch will be to (the destination) and is an offset from the current program counter and of course may be positive or negative.
A branch instruction is equivalent to a SuperBasic GOTO command. Much frowned upon by purists, but useful in certain situations. Never say 'Never use a GOTO' because in assembly language you almost always have one !
There are a number of 'branch' instructions that look at the condition codes and change the course of your program according to what they find. There are 14 of these and some appear remarkably similar to others. They are :
Branch | Name | Signed/unsigned | Description |
---|---|---|---|
BCC | Branch Carry Clear | Unsigned | The branch is executed if the carry flag is not set - ie zero. |
BCS | Branch Carry Set | Unsigned | The branch is executed if the carry flag is set - ie one. |
BEQ | Branch Equal | Both | Branch only if the result of the last operation caused the zero flag to be set. MOVEQ #0,D0 for example. |
BGE | Branch Greater or Equal | Signed | Branch if the last operation resulted in a signed number that was zero or greater. |
BGT | Branch Greater Than | Signed | Branch if the last result was greater that zero. |
BHI | Branch Higher | Unsigned | Branch if the last result was greater than zero. |
BLE | Branch Less or Equal | Signed | Branch if the last result was zero or less. |
BLS | Branch Low or Same | Unsigned | Same as BLE, but 'equal' replaced by 'same'. |
BLT | Bacon Lettuce & Tomato (only kidding !) Branch Less Than | Signed | Branch only if the last result was less than zero. |
BMI | Branch Minus | Signed | Branch if the result of the last operation was negative. Ie less than zero but not including zero. |
BNE | Branch Not Equal | Both | Branch if the last operation resulted in a non-zero outcome. CMPI.L #1,D1 if D1.L is not holding the value 1. |
BPL | Branch Plus | Signed | Branch if the result of the last operation is positive ie zero or greater. |
BVC | Branch oVerflow Clear | Both | branch is the last operation left the V flag unset. |
BVS | Branch oVerflow Set | Both | branch is the last operation left the V flag set. |
There is one more branch instruction that does not care about the flags, this is the BRA or Branch unconditionally instruction. It is the most like a GOTO instruction as that is its exact purpose - goto some other place in the program.
If the displacement value will fit into a single byte (-128 to +127) then a 'short' branch will take place. This entire instruction fits into a single word. If the displacement is zero, then this would normally indicate a short branch to the next instruction in the program. As this is where the PC is pointing anyway the zero displacement is used to signify a long branch and the word folloing is used as a 16 bit displacement allowing relative values between -32768 to +32767.
The short branch is written as Bcc.S with the dot and 's' indicating the shortness. Most assemblers default to the long branch which adds 2 bytes to your program for every Bcc instruction in it. I find the 'best' way to reduce the 'wasted' bytes is to make all branches short and the assembler will reject those which are out of range.
One of the most confusing aspects of assembly language programming for new and experienced coders alike is 'which are the signed and unsigned tests ?' I always have to look it up and I have never found a place where all the tests are listed together with the signed and unsigned comparisons. You won't have this problem as I have listed them all below.
Table 2.1. Signed & Unsigned Tests
Test for | Signed | Unsigned |
---|---|---|
Greater Equal | BGE | BCC |
Greater than | BGT | BHI |
Equal | BEQ | BEQ |
Not Equal | BNE | BNE |
Less Equal | BLE | BLS |
Less than | BLT | BCS |
Negative | BMI | Not applicable |
Positive | BPL | Not applicable |
In the above description of the Bcc instructions I state, for example, that the BNE instruction will branch if the last result was not zero. This is not quite the case. If I had just loaded a data register with some value which was not zero then the branch would be taken, as in the following fragment of code :
MOVE.L (A0),D1 BNE.S Somewhere
If, on the other hand, I was comparing two registers then the branch would have been taken if they did not have exactly the same contents :
CMP.L D3,D4 BNE.S not_equal BHI.S greater
So you can see that there are more ways to use these conditional branches. Bear in mind, however, that the CMP is simply a subtraction with the result 'thrown away' and it is that result that is being checked. One other area of confusion is which register is greater in the BHI instruction above ?
In a CMP instruction it should be read as Destination CMP source. If this is followed by a Bcc then it means branch if the destination is <condition> source. So in the above code fragment, we will branch to the label 'greater' if and only if D4 is greater than D3.
There are other instructions that affect the flow of a program and these are the 'looping' constructs or DBcc as they are written. These are the 'Decrement and branch UNTIL condition. Confused ? All will be revealed in the next chapter.