View Course Path

Branching Instructions in 8051

A microcontroller sequentially executes instructions but in some cases, transferring this control to another block of code becomes essential. The branching instructions in the 8051 microcontroller are responsible for performing this operation. Tasks like looping, calling delays, and conditional execution of code can be performed using these branching instructions.

But before we get into that, we would like to talk about the memory architecture of the ROM of the 8051. This is something very important and will help you understand the concepts mentioned later in the article. As we have repeated a few times in this 8051 course, the 8051 has a 16-bit address bus which gives it the ability to access 64KB of memory.

To understand this concept, let us make an analogy between a book and the memory of the 8051. So as a book is divided into pages of a certain number of words, the memory of 8051 is divided into pages of 2KB each. This concept of paging will come in handy when we discuss the concept of ACALL and AJMP. Paging or banking is a concept used to access larger address space.

Given below is a list of all the branching instructions in 8051. We will be talking about all these instructions in great detail in the coming sections so hang on and brew a cup of coffee because this can get pretty interesting.

List of Branching Instructions in 8051

Operation Mnemonics Description
Call
ACALL Address11 Calls a subroutine in the maximum address range of 2K bytes
LCALL Address16 Calls a subroutine in the maximum address range of 64K bytes
Return
RET Returns the control from subroutine
RETI Returns the control from an interrupt subroutine
Jump
AJMP Address11 Jumps to an address in a 2KB range
LJMP Address16 Jumps to an address in a 64KB range
SJMP Relative address Jumps to an address in a 256-byte range (0 to 127 (0-7FH) range and -1 to -128 (FFH-80H).
JMP @A+DPTR [DPTR]<-[DPTR+A]
JZ Relative address Jumps to address when accumulator=0
JNZ Relative address Jumps to address when accumulator!=0
CJNE A, Direct address, Relative address Jumps to relative address when accumulator=data stored at a direct address
CJNE A, #Data,Relative address Jumps to relative address when accumulator=data given by the programmer
CJNE @Rn, #Data,Relative address Jumps to relative address when data at memory location stored in register=data given by the programmer
DJNZ Rn, Relative address Decrements value in Rn and jump to relative address till Rn!=0
DJNZ Direct address, Relative address Decrements value at memory location stored in a register and jump to relative address till memory location stored in register =0

Call and Return instructions in 8051

In some cases, a microcontroller needs to perform the same tasks multiple numbers of times across the program, such as generating a delay. A subroutine is responsible for performing these repetitive tasks. Using subroutines saves memory and makes the program more efficient.

Instead of repeating the same few lines of code for some task you need to execute multiple times, you can just write it once and give it a label. Every time you need those lines to execute, just use the label to jump to the area where you had stored the labeled code. In essence, a subroutine is like a function, and it is placed at a different memory location then the program memory.

The call instruction is used to transfer the control from the presently executing program code to the subroutine, and the return instruction is used to return the control to the program code.

call_instruction_in_8051

Stack and control transfer

The stack of the 8051 plays a crucial role in the transfer of control when it comes to call instructions. When the call instruction executes, the program counter increments so that it points to the next instruction. The contents of the program counter are pushed into the stack (lower byte first). After this, the program counter is loaded with the starting instruction of the subroutine transferring the control.

Once the RET instruction is encountered, the contents stored in the stack are popped back into the program counter, and the microcontroller starts executing the program code from where it had left it.

One should take special care on using stack operations with call instructions as they use the stack for control transfer. The RET instruction is used to return from interrupt subroutines and works in the same way as the call instructions.

LCALL Instruction

Now that you are familiar with the working of the call instruction let us look at the LCALL instruction.

Opcode
Operand
Description
Size
Execution Time
Flags affected
Carry Overflow Auxilary carry
LCALL ADDRESS(16 BIT) Transfers the control to the specified address(64KB) 3 bytes 24 clock cycles Unaffected Unaffected Unaffected

The table given above shows that the LCALL instruction can access an address of 16 bits. Due to this reason, this instruction can access any memory location in the ROM space, but this instruction takes up 3 bytes of space and can waste memory resources. To save memory, the ACALL instruction is used.

Example

ORG 0000H; Directive for starting address of the program code
MOV A,#50H; Moves 50H into the accumulator
MOV R0,#25H; Moves 25H into the accumulator
LCALL Delay; Calls delay subroutine
ADD A, R0; Adds A and R0. stores the result in A
ORG 1000H; Directive for starting address of delay subroutine
DELAY: NOP; Performs no operation for 1 machine cycle
       NOP; Performs no operation for 1 machine cycle
       RET; Returns control to program code

ACALL Instruction

Opcode
Operand
Description
Size
Execution Time
Flags affected
Carry Overflow Auxilary carry
ACALL ADDRESS(11 BIT) Transfers the control to the specified address restricted to a page of 2KB 2 bytes 24 clock cycles Unaffected Unaffected Unaffected

The ACALL instruction is 2 bytes in size and can be used to access any address in a 2KB page. This instruction affects only 11 bits or the program counter as compared to 16 in the case of LCALL.

When this instruction is executed, the PC saves its current value on the stack, then the lower byte of the ADDRESS is stored in the lower byte section of PC, the remaining 3 bits of ADDRESS are stored in bits 0, 1, and 2 of PC. The bits 3-7 of the PC are empty.

Example

ORG 0000H; Directive for starting address of the program code
MOV A,#50H; Moves 50H into the accumulator
MOV R0,#25H; Moves 25H into the accumulator
ACALL Delay; Calls delay subroutine
ADD A, R0; Adds A and R0. stores the result in A
ORG 0300H; Directive for starting address of delay subroutine
DELAY: NOP; Performs no operation for 1 machine cycle
NOP; Performs no operation for 1 machine cycle
RET; Returns control to program code

RET Instruction

Opcode
Operand
Description
Size
Execution Time
Flags affected
Carry Overflow Auxilary carry
RET NONE Returns control to the program code 1 byte 24 clock cycles Unaffected Unaffected Unaffected
The RETI instruction is used to return from interrupt subroutines and works in the same way as the RET instruction if used outside a subroutine. When used inside a subroutine, RETI first enables interrupts of equal and lower priorities to the interrupt that it is used in. The program execution continues at the address that is calculated by popping the topmost 2 bytes off the stack. The most-significant-byte is popped off the stack first, followed by the least-significant-byte.

Jumps in 8051

The jump instruction is also used to transfer control in the 8051 microcontroller. But unlike a Call instruction, it does not call a subroutine and jumps to an address in the same program memory. Jumps in the 8051 microcontroller are used to perform looping and conditional execution of program code. Jumps in the 8051 are of two types

  1. Unconditional jumps- as the name suggests these jumps do not evaluate a condition to transfer the control to another address.
  2. Conditional jumps- these jumps evaluate a particular condition to transfer the control to another address in the program code. All conditional jumps are short jumps.

Unconditional jumps

 

Opcode
Operand
Description
Size
Execution Time
Flags affected
Carry Overflow Auxilary carry
LJMP ADDRESS(16 BITS) Transfers control within program code. The maximum range of this jump is 64KB 3 bytes 24 clock cycles Unaffected Unaffected Unaffected
AJMP ADDRESS(11 BITS) Transfers control within program code. The maximum range of this jump is 2KB 2 bytes 24 clock cycles Unaffected Unaffected Unaffected
SJMP Relative Address Uses the given address as an offset to the executing address and transfers the control to the new address. The maximum range of 256 bytes 2 bytes 24 clock cycles Unaffected Unaffected Unaffected

 

unconditional_jumps_in_8051
Difference between LJMP, AJMP, SJMP. The PC values change in the same way that they do for the LCALL and ACALL instructions.

Example

MOV   TMOD #0110000B ;sets counter1, mode 2,C/T=1(counts external pulses)
      MOV  TH1, #0  ;clears TH1 register
AGAIN:SETB P3.5     ;sets P3.5 as input port (all ports are configured as output ports by default)
BACK: MOV A,TL1     ;sends the value in TL1 to accumulator
      MOV P2, A     ;sends values to port 2
      JNB TF1,BACK  ;checks overflow condition
      CLR TR1       ;stops the counter
      CLR TF1       ;makes TF=0
      SJMP AGAIN    ;performs tasks infinitely

Conditional jumps in 8051

 

Opcode
Operand
Description
Size
Execution Time
Flags affected
Carry Overflow Auxilary carry
JZ Relative Address Uses the given address as an offset to the executing address and transfers the control to the new address if the value in the accumulator=0. The maximum range of 256 bytes 2 bytes 24 clock cycles Unaffected Unaffected Unaffected
JNZ Relative Address Uses the given address as an offset to the executing address and transfers the control to the new address if the value in the accumulator !=0. The maximum range of 256 bytes 2 bytes 24 clock cycles Unaffected Unaffected Unaffected
CJNE
A, Direct address, Relative address Compares the data stored in the accumulator with the data stored at the direct address. If the values are the same, then the control is transferred to the relative address 3 bytes 24 clock cycles Unaffected Unaffected Unaffected
A, #Data,Relative address Compares the data stored in the accumulator with the data given by the programmer. If the values are the same, then the control is transferred to the relative address 3 bytes 24 clock cycles Unaffected Unaffected Unaffected
@Rn, #Data,Relative address Compares the data stored at the address stored in the register with the data given by the programmer. If the values are the same, then the control is transferred to the relative address 3 bytes 24 clock cycles Unaffected Unaffected Unaffected
DJNZ
Rn, Relative address This instruction is used for looping in 8051. It decrements the value stored in Rn and jumps to the relative address till the value in the register!=0 2 bytes 24 clock cycles Unaffected Unaffected Unaffected
Direct address, Relative address This instruction is used for looping in 8051. It decrements the value stored at the given address and jumps to the relative address till the value in the address!=0 3 bytes 24 clock cycles Unaffected Unaffected Unaffected

Example 

The program given below adds 3 ten times to the accumulator. It uses the DJNZ instruction for looping.

MOV A,#0; clears the accumulator
MOV R2,#10; moves 10 into r2 which cats as a counter
AGAIN: ADD A,#03; adds 3 into the accumulator till r2!=0
       DJNZ R2,AGAIN; decrements value in r2 and jumps to again label till value !=0
       MOV R5,A; Moves the result into R5

Now that you understand branching instructions, you can better understand the process of subroutines and interrupts. If you’ve noticed, some of the branching instructions here operate on single bits of data instead of entire bytes. In the next post, we will summarize all the bit-wise instructions in the 8051 instruction set.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.