Conditional Jump
The conditional jump instruction is required for making decisions in the program.
Instructions to change the program sequence depending on, for instance, the result of a calculation or a test on an input, are an essential feature of any microprocessor instruction set.
In Figure 2.3, the code 1885 tests an input bit of the PIC and skips the next instruction if it is zero. Instruction YYYY (representing any valid instruction code) is then executed. If the input bit is high, the instruction 2807 is executed, which causes a jump to address 007, and instruction ZZZZ is executed next. This is called Bit Test and Skip, and is the way that conditional branches are achieved in the PIC.
In PIC assembly language, this program fragment looks like this:
The PIC is designed with a minimal number of instructions, so the conditional branch has to be made up from two simpler instructions. The first instruction tests a bit in a register and then skips (misses out) the next instruction, or not, depending on the result. This next instruction is usually a jump instruction (GOTO or CALL). Thus, program execution continues either at the instruction following the jump, if the jump is skipped, or at the jump destination.
The program outline of a conditional jump used in a delay routine, would look like this:
This software timing loop simply causes a time delay in the program, which is useful, for instance, for outputting signals at specific intervals. A register is used as a down counter by loading it with a number, XX, and decrementing it repeatedly until it is zero. A test instruction then detects that the zero flag has gone active, and the loop is terminated. Each instruction takes a known time to execute, therefore the delay can be predicted.
An example of a conditional jump can be seen at lines 39 and 40 in the keypad program, where BTFSS DIGIT,4 is followed by GOTO Next, so that the jump back is only executed if bit 4 of the register labelled DIGIT (GPR 20) is zero.
Subroutine
Subroutines are used to carry out discrete program functions. They allow programs to be written in manageable, self-contained blocks, which are then executed as required, often more than once per program cycle. The instruction CALL is used to jump to a subroutine, which must be terminated with the instruction RETURN.
CALL has the address of the first instruction in the subroutine as its operand. When the CALL instruction is decoded, the destination address is copied to the PC, as in the GOTO instruction. In addition, the address of the next instruction in the main program is saved in the ‘stack’, a special set of registers. The return address is ‘pushed’ onto the stack when the subroutine is called, and ‘pulled’ back into the program counter at the end of the routine, when the RETURN instruction is executed. These addresses are automatically stored in order and retrieved in reverse order.
In Figure 2.4, the subroutine is a block of code whose start address has been defined by label as 0F0. The CALL instruction at address 002 contains the destination address as its operand. When this instruction is encountered, the processor carries out the jump by copying the destination address (F0h) into the program counter. At the same time, the address of the next instruction in the main program (003) is pushed onto the stack, so that the program can come back to the original point after the subroutine has been executed.
One advantage of using subroutines is that the block of code can be used more than once in the program, but only needs to be typed in once. A delay loop can be written as a subroutine. In a program to generate an output pulse train, it can be ‘called’ twice within a loop, which sets an output high, delays, sets the output low, and delays again before repeating the whole process. The delay subroutine can be written such that it takes its delay count from W each time it is called, making it a variable delay routine, as shown in the outline below:
An example of a subroutine call is included in the keypad program at line 38, CALL Scan, which causes a jump to the subroutine starting at line 54. RETURN is encountered at line 83, when the execution continues from line 39.
A simple application will be developed in the next chapter to illustrate the basic principles of assembly language programming.
1. Outline the sequence of program execution in a microcontroller, describing the role of the program memory, program counter, instruction register, instruction decoder, and timing and control block. (5)
2. A register is loaded with the binary code 01101010. The carry bit is set to zero. State the contents of the register after the following operations on this data (refer to PIC MCU data sheet for exact effects):
(a) clear, (b) increment, (c) decrement, (d) complement, (e) rotate right, (f) shift left,
(g) clear bit 5, (h) set bit 0. (8)
3. A source register is loaded with the binary code 01001011, and a destination register loaded with 01100010. State the contents of the destination register after the following operations:
(a) MOVE, (b) ADD, (c) AND, (d) OR, (e) XOR. (5)
4. In a microcontroller program, a subroutine starts at address 016F and ends with a ‘return’ instruction at address 0172. A ‘call subroutine’ instruction is located at address 02F3. Assuming that the microcontroller has one complete instruction in each address, list the changes in the contents of the program counter and stack between the time of execution of the instruction before the call and the instruction following the call. Indicate an unknown value as XXXX. (5)
5. Write a program outline for the process by which two numbers, say 4 and 3, could be multiplied by successive addition. Use the register instructions Clear, Move, Add, Decre- ment, Test for Zero and Jump if Zero to Label. Load a register with zero, and add 4 to it three times by using a counter initially loaded with 3 and decremented to zero to control the loop. (7)
Answers on page 417 (Total 30 marks)
Activities 2
Download the PIC 16F84A data sheet from www.microchip.com.
1. Study the PIC 16F84A block diagram (data sheet Figure 1-1), and identify the features described in Section 2.1. Note the separate internal instruction and data buses, and summarize the function of each block. Describe how data is moved between registers and memory, and the function of the multiplexers (refer to Appendix C).
2. Study the PIC Instruction Set (data sheet Table 7-2). Note the format of the binary code for each instruction, and identify the meaning of the symbols f, b, k, d, x, C, DC and Z. Explain why some instructions take two cycles.
3. Study the list file generated for program BIN4 shown in Figure 4-4, noting the machine code at the lower left. The program memory addresses from 0000 to 000F appear in column 1, and the machine code instructions appear in column 2. Refer to the instruction set in the PIC 16F84A data sheet, and analyze the program by deducing the code for each instruction and operand, identifying SFR and GPR addresses, register bits, destination bit, address labels and literal values as appropriate. Complete the table below (for all addresses from 0004 through 000F), analyzing each instruction e 0000 to 0003 have been completed as an example: