Loops

A loop is a jump back to an earlier label. The 8086 has an instruction made for counting loops, LOOP:

LOOP L takes 1 from CX, then jumps to L if CX is not 0. So with CX = n, the loop body runs n times.

; Print the digits 0 to 9 with LOOP.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV CX, 10         ; ten times
    MOV DL, '0'        ; the first digit
AGAIN:
    MOV AH, 2
    INT 21H            ; print DL
    INC DL             ; the next digit
    LOOP AGAIN         ; CX = CX - 1; jump back while CX is not 0
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN
Open in compiler

While-loops

When the number of repeats is not known in advance, test a condition with CMP and a conditional jump, at the top (a while-loop) or at the bottom (a do-while):

AGAIN:
    CMP AL, 0DH      ; while AL is not Enter
    JE DONE
    ...              ; the loop body
    JMP AGAIN
DONE:

The CX = 0 trap

LOOP takes 1 from CX before testing it. If CX is 0 when the loop starts, it becomes FFFFh, and the body runs 65536 times. JCXZ L (jump if CX is zero) skips a loop safely:

    JCXZ SKIP        ; nothing to do
AGAIN:
    ...
    LOOP AGAIN
SKIP:

LOOPE and LOOPNE also stop early when ZF is 0 or 1, for searching.

Loops inside loops

Both loops would need CX. The usual answer is to save the outer count on the stack while the inner loop uses CX, with PUSH CX and POP CX (the stack is lesson 11):

; A triangle of stars: row n has n stars (a loop inside a loop).
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV BX, 1          ; stars in this row
    MOV CX, 3          ; rows
ROW:
    PUSH CX            ; save the row count
    MOV CX, BX         ; the inner loop counts stars
STAR:
    MOV DL, '*'
    MOV AH, 2
    INT 21H
    LOOP STAR
    MOV DL, 0DH        ; new line
    INT 21H
    MOV DL, 0AH
    INT 21H
    INC BX             ; one more star next row
    POP CX             ; back to the row count
    LOOP ROW
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN
Open in compiler

Common mistakes

  • Starting a LOOP with CX = 0: it runs 65536 times.
  • Changing CX inside the loop body by accident (for example with a MUL or a string instruction).
  • A conditional loop whose condition never changes: StepVioz stops it after 1000 steps in the visualizer.
  • Forgetting to POP CX back before the outer LOOP, or popping twice.

Quick check

1. CX = 4. How many times does a body ending in LOOP run?
2. What happens if CX = 0 when a LOOP loop starts?
3. What does JCXZ do?
4. Why do nested loops often PUSH CX before the inner loop?

Practice problems for this lesson

My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.