Jump, Loop and Call Instructions

After you have understood the tutorial on Introduction to assembly language which includes simple instruction sets like input/output operations,  now it’s time to learn how to create loops, function calls and jumps while writing a code in assembly language.

Let us first discuss an important concept that relates RAM & ROM. You can skip this section if you wish but it is an important to understand registers which helps in building up understanding of architecture of microcontrollers.

How a program which is burned in ROM gets executed in RAM?

The program you write is burned in ROM and this program is executed in RAM. The data burned is in the form of logics or binary digits (0 & 1) also called an Opcode or machine code. The program written in assembly language is converted to opcode by assembler.

Each line of the assembly code is assigned a unique opcode by the assembler as shown below. These opcodes are then stored in ROM one after another. There is a register called Program Counter (PC) which always points to the current opcode being executed. When the power is switched on it sets itself to zero and it keeps on incrementing itself as opcodes are executed one after another. This information is used by RAM to extract correct opcode from ROM which is then executed. This process goes on line by line till the whole program is executed.


How a program burned in ROM gets executed in RAM?


Let’s take an example:-

PC                                           Mnemonic, Operand          Opcode (Machine code)              

0000                                             ORG       0H                                                                          

0000                                             MOV      R0, #0                      7800

0002                                             MOV      A, #55H                                                                7455

0004                                             JZ           NEXT                        6003

0006                                             INC         R0                            08

0007             AGAIN:                     INC         A                              04

0008                                             INC         A                              04

0009             NEXT:                       ADD       A, #77H                    2477

000B                                             JNC         OVER                        5005

000D                                            CLR         A                               E4

000E                                             MOV       R0, A                         F8

000F                                             MOV       R1, A                         F9

0010                                             MOV       R2, A                         FA

0011                                             MOV       R3, A                         FB

0012            OVER:                       ADD,       R3                             2B

0013                                             JNC         AGAIN                       50F2

0015             HERE:                       SJMP        HERE                          80FE

0017                                             END

We can clearly see that the PC increases with execution of program. The PC starts with zero when ‘ORG 00H’ line is executed and then in subsequent lines PC keeps on incrementing  as machine codes are executed one after another.

Program Counter is a 2 byte or 16 bit register.  Therefore we cannot have internal ROM of more than the number this register can hold (i.e. not exceeding the FFFF hex value).




Let us start with a simple example that will help you to learn how to create loops in assembly. In the following code the instruction DJNZ is used to reduce the counter and is repeated till the counter becomes zero.


                    ORG     0H

        MOV    A, #0                  ; clear A

        MOV    R1, #10              ; load counter R1 =10

AGAIN:         ADD     A, # 05              ; add five to register A

        DJNZ    R1, AGAIN         ; repeat until R1=0 (10 times)

        MOV    R3, A                  ; save A in R3



In this code R1 acts as a counter. The counter value is initialized i.e. 10 HEX is loaded to R1. In each iteration, the instruction DJNZ decrements R1 by one until it becomes zero. This loop adds 5 HEX to A every time it runs. After ten iterations R1 becomes zero and the instructions below it are executed.

Note: - Some Jump statements can only be performed on some special register A (or bit CY) as mentioned in the table below.



Nested loops:

                            ORG 0H

                MOV    A, #55H                  ; A= 55 hex

                MOV    R1, #100                ; the outer counter R1 =100

NEXT:                   MOV    R2, # 20                 ; the inner counter

AGAIN:                 CPL      A, # 05                  ; add five to register A

    DJNZ    R2, AGAIN             ; repeat until R1=0 (100 times)

    DJNZ    R1, NEXT               ; repeat till 20 times (outer loop)



SJMP refers to short jump and LJMP refers to long jump. All the conditional jumps are short jumps.

SJMP: This instruction is of two bytes in which first one is opcode & second is the address. The relative address of the instruction called should be in between -127 to 127 bytes from the current program counter (PC).

LJMP: This instruction is of three bytes in which the first is the opcode and the second & third are for address. The relative address of the instruction can be anywhere on the ROM.

So it is clear from the above examples that we can use different jump instructions with a condition or counter called conditional loop. And when we create loop inside an existing loop it is called nested loop.






LCALL (long call)

ORG      0H

BACK :              MOV     A, #55H                                  ; load A= 55 hex value

                        MOV     P1, A                                       ; issue value of register A to port1

                        LCALL  DELAY                                      ; to call DELAY function created below

                        MOV A, #0AAH                                    ;load AAH hex value to A

                        MOV P1,A                                            ;issue value of register A to port 1

LCALL   DELAY                                     ; to call DELAY function as created below

SJMP     BACK                                        ; keep doing this

; ________ this is the delay subroutine



                            MOV         R5, #0FFH                       ; R5= 255 hex, the counter

AGAIN:                 DJNZ     R5, AGAIN                           ; stay here until R5 becomes zero

                RET                                                         ; return to caller


In this code we keep on toggling the value of the register of port 1 with two different hex values and a DELAY subroutine is used to control how fast the value is changing. Here in DELAY subroutine the program is kept busy by running an idle loop and counting 256 counts.  After the DELAY subroutine is executed once the value of port 1 is toggled and this process goes on infinitely.

By using DELAY we can create PWM (Pulse Width Modulation) to control motors or LED blinking for further details view our tutorial on Input/ output instructions in Assembly Language[coming soon].

We can also use ACALL i.e. absolute call for calling a subroutine that is within 2K byte of PC.