Comparing and jumping

Assembly has no if. Instead, CMP compares two values and conditional jumps go to a label or carry on, depending on the flags CMP set.

CMP a, b works out a − b like SUB, sets the flags, and throws the answer away: a does not change.

The jumps

JumpJumps ifReads
JMP Lalways
JE L / JZ Lequal / zeroZF = 1
JNE L / JNZ Lnot equalZF = 0
JG L / JGE Lgreater / greater or equal, signedZF, SF, OF
JL L / JLE Lless / less or equal, signedSF, OF, ZF
JA L / JAE Labove / above or equal, unsignedCF, ZF
JB L / JBE Lbelow / below or equal, unsignedCF, ZF

A label is a name followed by a colon, marking an instruction: BIGGER:.

if and if-else

An if-else becomes: compare, jump over the "then" part when the condition is false, and after the "then" part jump over the "else" part:

; Read two digits and print the larger one.
.MODEL SMALL
.STACK 100H
.DATA
    SAY DB 0DH, 0AH, 'Larger: $'
.CODE
MAIN PROC
    MOV AX, @DATA
    MOV DS, AX
    MOV AH, 1
    INT 21H
    MOV BL, AL         ; first digit (as a character)
    MOV AH, 1
    INT 21H
    MOV BH, AL         ; second digit
    LEA DX, SAY
    MOV AH, 9
    INT 21H
    CMP BL, BH         ; if BL >= BH ...
    JAE FIRST          ; ... the first is the larger
    MOV DL, BH         ; else: the second
    JMP SHOWIT         ; skip the 'then' part
FIRST:
    MOV DL, BL
SHOWIT:
    MOV AH, 2
    INT 21H
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN

Input used: 48

Open in compiler

The CPU view shows CMP's flags, and the explanation under the code says why each jump was taken or not.

Signed or unsigned?

The bits FFh are 255 unsigned but −1 signed, so whether FFh is "greater" than 1 depends on the jump you choose. JA/JB treat values as unsigned (they read CF), JG/JL as signed (they read SF and OF):

; The same bits compared as unsigned and as signed numbers.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV AL, 0FFH       ; 255 unsigned, -1 signed
    MOV BL, 1
    MOV DL, 'n'
    CMP AL, BL
    JA ABOVE           ; unsigned: 255 > 1, so it jumps
    JMP TEST2
ABOVE:
    MOV DL, 'A'
TEST2:
    MOV AH, 2
    INT 21H            ; prints A
    MOV DL, 'n'
    CMP AL, BL
    JG GREATER         ; signed: -1 > 1 is false, so no jump
    JMP DONE
GREATER:
    MOV DL, 'G'
DONE:
    MOV AH, 2
    INT 21H            ; prints n
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN
Open in compiler

Use JA/JB for codes, counts and addresses, and JG/JL for numbers that may be negative.

Common mistakes

  • Forgetting the jump over the else part, so both parts run.
  • Using JG for characters or other unsigned values above 127; use JA.
  • Writing the label without a colon where it is defined (BIGGER instead of BIGGER:).
  • Putting an instruction that changes the flags (ADD, INC, ...) between CMP and the jump that reads them. MOV does not change flags.

Quick check

1. What does CMP AX, BX change?
2. AL = FFh, BL = 1. CMP AL, BL. Which jump is taken?
3. Which flag does JE read?
4. In an if-else, why is there a JMP at the end of the 'then' part?

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.