User Tools

Site Tools


content:pic:branch_instructions

PIC18: branch instructions

Skimming through the PIC 18F4550 istruction set we can see, among others, a bunch of 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.

Branch instructions

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.

Carry bit

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

Zero bit

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

content/pic/branch_instructions.txt · Last modified: 2022/07/02 11:22 by admin