Detailed Explanation of the LOOP Instruction in Assembly Language

Overview of the LOOP Instruction

The LOOP instruction is a loop control instruction in 8086 assembly language, combining the functionality of decrementing a counter and conditional branching. This instruction is a short jump instruction, with a jump range limited to -128 to 127 bytes.

Instruction Format and Functionality

Instruction Format: <span>loop label</span>

Functionality:

  1. First, decrement the value in the CX register: (CX) = (CX) – 1
  2. Then check the value of CX:
  • If (CX) ≠ 0, jump to the label to execute
  • If (CX) = 0, continue executing the next instruction

Operational Principle:

  • When (CX) ≠ 0, (IP) = (IP) + 8-bit displacement
  • 8-bit displacement = address of the label – address of the first byte after the loop instruction
  • The range of 8-bit displacement is -128 to 127, represented in two’s complement
  • The 8-bit displacement is calculated by the compiler at compile time

Correspondence with High-Level Languages

Functionally, <span>loop label</span> is equivalent to the following C language code:

cx--;
if (cx != 0) {
    goto label;
}

Or expressed in assembly language:

dec cx
jnz short label

Code Examples

Example 1: Basic Loop

; Example 1: Basic usage of loop
org 100h

start:
    mov cx, 5       ; Set loop count
    mov ax, 0       ; Initialize accumulator

sum_loop:
    add ax, cx      ; Accumulate current cx value
    loop sum_loop   ; Decrement cx, if cx ≠ 0 then loop

    ; After the loop ends, ax = 5+4+3+2+1 = 15

    mov dx, offset result_msg
    mov ah, 09h
    int 21h         ; Display result message

    mov ax, 4C00h
    int 21h         ; Program exit

result_msg db 'Loop finished!$'

Example 2: String Processing

; Example 2: Using loop to process strings
org 100h

start:
    mov si, offset string  ; Address of the string
    mov cx, 0              ; Initialize counter

    ; First, calculate the length of the string
count_chars:
    cmp byte ptr [si], '$' ; Check if end of string
    je setup_loop          ; If so, end counting
    inc cx                 ; Increase count
    inc si                 ; Move to the next character
    jmp count_chars        ; Continue looping

setup_loop:
    mov si, offset string  ; Repoint to the start of the string

    ; Use loop to convert the string to uppercase
to_upper:
    mov al, [si]           ; Get character
    cmp al, 'a'            ; Check if lowercase letter
    jb next_char
    cmp al, 'z'
    ja next_char
    sub al, 32             ; Convert to uppercase
    mov [si], al           ; Store back to original position

next_char:
    inc si                 ; Move to the next character
    loop to_upper          ; Loop to process all characters

    ; Display the converted string
    mov dx, offset string
    mov ah, 09h
    int 21h

    mov ax, 4C00h
    int 21h

string db 'hello, world!$'

Example 3: Nested Loops

; Example 3: Using nested loops
org 100h

start:
    mov cx, 3       ; Outer loop count

outer_loop:
    push cx         ; Save outer loop counter
    mov cx, 4       ; Inner loop count

inner_loop:
    ; Inner loop processing code
    mov dl, '*'     ; Display asterisk
    mov ah, 02h
    int 21h

    loop inner_loop ; Inner loop

    ; New line
    mov dl, 0Dh     ; Carriage return
    mov ah, 02h
    int 21h
    mov dl, 0Ah     ; New line
    mov ah, 02h
    int 21h

    pop cx          ; Restore outer loop counter
    loop outer_loop ; Outer loop

    mov ax, 4C00h
    int 21h

Example 4: Array Processing

; Example 4: Using loop to process an array
org 100h

start:
    mov cx, 10              ; Number of array elements
    mov si, offset array    ; Address of the array
    mov ax, 0               ; Initialize accumulator

sum_array:
    add ax, [si]            ; Accumulate array elements
    add si, 2               ; Move to the next word element
    loop sum_array          ; Loop to process all elements

    ; At this point, ax contains the sum of the array elements

    ; Convert result to string for display
    mov di, offset result_str + 5  ; Point to end of string
    mov byte ptr [di], '$'         ; String terminator

convert_loop:
    dec di                  ; Move to previous character position
    mov dx, 0               ; Clear dx, prepare for division
    mov bx, 10              ; Divisor
    div bx                  ; ax/10, quotient in ax, remainder in dx
    add dl, '0'             ; Convert remainder to ASCII character
    mov [di], dl            ; Store character

    test ax, ax             ; Check if quotient is 0
    jnz convert_loop        ; If not 0, continue converting

    ; Display result
    mov dx, di
    mov ah, 09h
    int 21h

    mov ax, 4C00h
    int 21h

array dw 1, 2, 3, 4, 5, 6, 7, 8, 9, 10  ; Array of words
result_str db '00000$'                   ; Result string

Characteristics and Considerations of the LOOP Instruction

  1. Short Jump Limitation: The LOOP instruction is a short jump instruction, with a jump range of only -128 to 127 bytes. If the target address exceeds this range, the assembler will report an error.

  2. Counter Usage: The LOOP instruction specifically uses the CX register as a counter, and the value of CX must be set correctly before execution.

  3. Efficiency Consideration: The LOOP instruction combines decrementing the counter and conditional jumping into a single instruction, improving code efficiency and compactness.

  4. Difference from JCXZ Instruction:

  • The LOOP instruction first executes CX = CX – 1, then checks if CX ≠ 0 to loop
  • The JCXZ instruction directly checks if CX = 0 to jump, without modifying the value of CX
  • Applicable Scenarios:

    • Fixed count loops
    • Array and string processing
    • Loop control requiring compact code

    Comparison with Other Loop Instructions

    The 8086 assembly language provides several similar loop instructions:

    1. LOOP: Loops while CX ≠ 0
    2. LOOPE/LOOPZ: Loops while CX ≠ 0 and ZF = 1
    3. LOOPNE/LOOPNZ: Loops while CX ≠ 0 and ZF = 0

    All these instructions use CX as a counter and are short jump instructions.

    Common Errors and Solutions

    1. Jump Range Exceeded Error:

      ; Error example: Loop body too large, exceeds short jump range
      mov cx, 100
      big_loop:
          ; Large amount of code...
          loop big_loop  ; May cause error
      
      ; Solution: Use near jump
      mov cx, 100
      big_loop:
          ; Large amount of code...
          dec cx
          jnz big_loop
      
    2. CX Register Modified Unexpectedly:

      ; Error example: CX modified within the loop body
      mov cx, 10
      my_loop:
          ; Processing code...
          mov cx, 5  ; Error: Modified loop counter
          loop my_loop
      
      ; Solution: Protect the CX register or use another register
      mov cx, 10
      my_loop:
          ; Processing code...
          push cx    ; Save CX
          mov cx, 5  ; Use CX for other tasks
          ; ...
          pop cx     ; Restore CX
          loop my_loop
      

    Conclusion

    The LOOP instruction is an efficient loop control instruction in 8086 assembly language, combining decrementing a counter and conditional jumping into a single instruction. By using the LOOP instruction appropriately, one can write compact and efficient loop code, especially suitable for fixed count loops, array processing, and string operations.

    It is important to note that the LOOP instruction is a short jump instruction with a limited jump range and specifically uses the CX register as a counter. In actual programming, one should choose the appropriate loop control method based on specific needs and be cautious to avoid common erroneous usages.

    Leave a Comment