Table of Contents
PIC18: branch instructions
What are they for and what's their relationship with the STATUS register? Let's see them in practice using some assembly code examples. This will also be a nice occasion to do a bit of simple HEX math.
BC - Branch if Carry
BN - Branch if Negative
BNC - Branch if Not Carry
BNN - Branch if Not Negative
BNOV - Branch if Not Overflow
BNZ - Branch if Not Zero
BOV - Branch if Overflow
BRA - Branch Unconditionally
BZ - Branch if Zero
Those instructions make the program counter (PC) jump to another part in the program code on the evaluation of the STATUS register (that's not true for the BRA instruction which branches unconditionally).
So it's important to understand the various flags of this register and how they are affected by the execution of other instructions; for this purpose we are going to use a great piece of Windows software named PIC18 Simulator IDE, which runs fine under Linux thanks to Wine.
The STATUS register
Every flag in the STATUS register can be intercepted by the correspondent branch instruction; let's see this in practice.
This is the first code we are going to assemble and load onto PIC18 Sim:
processor 18F4550 INCLUDE <p18f4550.inc> testreg equ 0x00 org 0x00 goto Start org 0x08 nop org 0x18 nop Start movlw .1 movwf testreg ; Main loop Main movlw .4 addwf testreg bra Main END
testreg is defined as a file register located at 0x00 and loaded with .1 Then what the Main loop does is adding the value .4 to it over and over again to see how that's reflected on the STATUS register.
Digit carry bit
The values that testreg goes through are: 1h, 5h, 9h, Dh. Let's stop here and do the next operations by ourselves.
0Dh + 04h = ___ 11h
There is a carry for the lower nibble, which is added to the higher nibble; it is called a digit carry and that situation is reflected on bit 1 of the STATUS register:
Overflow and negative bits
Let's go on and keep adding .4 to testreg until we come to the value 7Dh and do the math:
7Dh + 04h = ___ 81h
Like before we have a digit carry (a carry resulting from the addition of the lower nibbles) ; as for the higher nibble, its most significant bit is on and that corresponds, in 2's complement notation, to a negative number: that turns on bit 4 of the STATUS reg.
That alone doesn't make the number negative; it all depends on the instruction that uses the operand (the register) to interpret it as a signed number or a positive one.
There is also an overflow, a condition which is met when there is a change in the sign, from positive to negative as in this case: bit 3 is therefore also on.
In the next situation testreg is now FDh:
FDh + 04h = ____ 101h
The result i 101h, but since testreg, as all GPRs, is an 8 bit register the leading '1' is truncated and 01h is instead saved; both the higher and lower nibble had a carry, so bit 0 (carry) is also on:
The Carry bit (but not the Digit Carry) is also affected by register rotate instructions like RLCF (Rotate Left f through Carry) and RRCF (Rotate Right f through Carry):
Start movlw .1 movwf testreg ; Main loop Main rrcf testreg,F bra Main
This should be simple; for example:
Start movlw .255 movwf testreg ; Main loop Main incf testreg,F bra Main
We can see that bit 2, the STATUS bit that intercepts operations which lead to a result equal to Zero, is turned on, but also bit 0 (Carry) and bit 1 (Digit Carry). Let's try to explain that:
FFh + 01h = ____ 100h
When we sum the lower nibbles (Fh + 1h) we have a carry, so Digit Carry bit is on; the carry is then added to the higher nibbles (1h + Fh + 0), which makes the Carry bit on.
Borrow and Digit borrow bits
Carry and Digit Carry bits are affected by additions; but when numbers are subtracted they become Borrow and Digit Borrow bits, which are active low; this means that when there is a borrow the bits are off.
Start movlw .1 movwf testreg ; Main loop Main decf testreg,F bra Main
In the above example the subtraction is:
01h - 01h = ___ 00h
First the lower nibbles are subtracted (1h - 1h); there's no borrow so Digit Borrow bit (bit 1) is on; then the higher nibbles are subtracted (0 - 0): no borrow so Borrow bit (bit 0) is on:
(Zero bit - bit 2 - is also on)
If we go further with the next subtraction:
00h - 01h = ___ FFh
The lower nibbles are subtracted: there's a need for borrow (Digit Borrow bit off), which is also needed in turn by the higher nibbles (Borrow bit off):
(Negative bit - bit 4 - is also on)
With the following subtraction only the Digit Borrow bit is affected and so it is turned off:
F0h - 01h = ___ EFh