Assembly Language - Conditional Judgment

Conditional judgment is the cornerstone of program control flow. Assembly language implements judgment logic such as if-else, switch, etc., through compare instructions and conditional jump instructions.


CMP - Compare Instruction

CMPPerforms a subtraction operation on two operands (destination - source), but does not save the result, only updates the flags.

EssentiallyCMP dest, srcEquivalent toSUB dest, srcBut discards the calculation result.

Example

; CMP compare instruction example

section .text
    global _start

_start:
    mov eax, 10
    cmp eax, 10                 ; eax == 10?
    ; ZF = 1 (equal, result is zero)
    ; CF = 0 (no borrow)
    ; SF = 0 (result non-negative)

    mov eax, 5
    cmp eax, 10                 ; eax == 10?
    ; ZF = 0 (not equal, result non-zero)
    ; CF = 1 (borrow: 5 < 10)

    mov eax, 20
    cmp eax, 10                 ; eax == 10?
    ; ZF = 0 (not equal)
    ; CF = 0 (no borrow: 20 >= 10)
    ; SF = 0 (result non-negative: 10 > 0)

    mov eax, 1
    mov ebx, 0
    int 0x80

Conditional Jump Instructions

Conditional jump instructions determine whether to jump based on the state of the flags. If the condition is true, jump to the target label; otherwise, continue executing the next instruction.

InstructionMeaningFlags CheckedApplicable Scenario
JE / JZJump if equal / zeroZF = 1cmp a, bCheck a == b after CMP
JNE / JNZJump if not equal / not zeroZF = 0cmp a, bCheck a != b after CMP
JG / JNLEJump if greater (signed)ZF=0 and SF=OFSigned numbers a > b
JGE / JNLJump if greater or equal (signed)SF = OFSigned numbers a >= b
JL / JNGEJump if less (signed)SF != OFSigned numbers a < b
JLE / JNGJump if less or equal (signed)ZF=1 or SF!=OFSigned numbers a <= b
JA / JNBEJump if above (unsigned)CF=0 and ZF=0Unsigned numbers a > b
JAE / JNBJump if above or equal (unsigned)CF = 0Unsigned numbers a >= b
JB / JNAEJump if below (unsigned)CF = 1Unsigned numbers a < b
JBE / JNAJump if below or equal (unsigned)CF=1 or ZF=1Unsigned numbers a <= b

Many instructions have two aliases (such as JE and JZ), which are exactly the same at the machine code level. Which one to use depends on the context: use JE/JNE after comparisons, and JZ/JNZ after checking operation results. This improves code readability.


Single-Branch IF Structure

Example

; File path: if_demo.asm
; Implementation: if (x > 10) x = 10;

section .data
    x dd 15                     ; Test value
    limit dd 10

section .text
    global _start

_start:
    mov eax, [x]                ; Load x into eax
    cmp eax, [limit]            ; x > 10 ?
    jle skip_update             ; If x <= 10, skip update

    mov dword [x], 10           ; x = 10

skip_update:
    ; Program continues... (here x is already 10)

    mov eax, 1
    mov ebx, 0
    int 0x80

IF-ELSE Double-Branch Structure

Example

; File path: if_else_demo.asm
; Implementation: if (score >= 60) grade = 'P' else grade = 'F'

section .data
    score dd 75                 ; Exam score
    grade db 0                  ; Grade
    PASS_SCORE equ 60

section .text
    global _start

_start:
    mov eax, [score]            ; Load score
    cmp eax, PASS_SCORE         ; score >= 60 ?
    jge pass_label              ; If >= 60, jump to pass

    ; else branch: fail
    mov byte [grade], 'F'       ; grade = 'F'
    jmp end_if                  ; skip if branch

pass_label:
    ; if branch: pass
    mov byte [grade], 'P'       ; grade = 'P'

end_if:
    ; grade variable is now set

    ; output grade
    mov eax, 4
    mov ebx, 1
    mov ecx, grade
    mov edx, 1
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80

Run result:

$ nasm -f elf32 if_else_demo.asm -o if_else_demo.o
$ ld -m elf_i386 if_else_demo.o -o if_else_demo
$ ./if_else_demo
P

IF-ELSE IF-ELSE Multi-Branch Structure

Below uses a score grading system as an example to show the flow of multi-branch decision:

条件判断多分支流程图

Example

; File path: multi_branch.asm
; Score grading: >=90 -> A, >=80 -> B, >=70 -> C, >=60 -> D, <60 -> F

section .data
    score dd 85
    result db 0
    newline db 0xA

section .text
    global _start

_start:
    mov eax, [score]            ; Load score

    ; Check >= 90
    cmp eax, 90
    jl check_80                 ; If < 90, continue checking
    mov byte [result], 'A'
    jmp print_result

check_80:
    cmp eax, 80
    jl check_70
    mov byte [result], 'B'
    jmp print_result

check_70:
    cmp eax, 70
    jl check_60
    mov byte [result], 'C'
    jmp print_result

check_60:
    cmp eax, 60
    jl fail_label
    mov byte [result], 'D'
    jmp print_result

fail_label:
    mov byte [result], 'F'

print_result:
    ; Output grade
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 0x80

    ; Output newline
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80

TEST - Non-Destructive Test Instruction

TESTPerforms bitwise AND but does not save the result, only updates flags.

TESTOften used to check whether a specific bit is 1, or whether a register is 0.

Example

; TEST instruction example

    ; Check if eax is 0 (more efficient than CMP eax, 0)
    test eax, eax               ; eax & eax = eax, only updates ZF
    jz  eax_is_zero             ; If ZF=1, then eax=0

    ; Check a specific bit
    test al, 0x01               ; Check if bit0 is 1
    jnz bit0_is_set             ; If bit0=1, jump

    ; Check multiple bits
    test al, 0x03               ; Check if at least one of bit0 and bit1 is 1
    jnz some_bit_set

SETcc - Conditional Set Instruction

Instead of jumping, sets the destination byte to 1 or 0 based on the condition:

Example

; SETcc conditional set example

    ; Store result of a > b into al
    mov eax, 10
    cmp eax, 5                  ; 10 > 5 ?
    setg al                     ; al = 1 (greater than holds)
    ; If eax = 3, then al = 0

    ; Other SETcc instructions:
    ; sete / setz -> equal/zero
    ; setne / setnz -> not equal/not zero
    ; setl -> less than (signed)
    ; setb -> less than (unsigned)
    ; setg -> greater than (signed)
    ; seta -> greater than (unsigned)

Complete Example: Determine Odd/Even and Positive/Negative

Example

; File path: number_check.asm
; Determine if number is odd/even, positive/negative

section .data
    number dd -42
    msg_even db 'Even', 0xA
    msg_even_len equ $ - msg_even
    msg_odd db 'Odd', 0xA
    msg_odd_len equ $ - msg_odd
    msg_pos db 'Positive', 0xA
    msg_pos_len equ $ - msg_pos
    msg_neg db 'Negative', 0xA
    msg_neg_len equ $ - msg_neg
    msg_zero db 'Zero', 0xA
    msg_zero_len equ $ - msg_zero

section .text
    global _start

_start:
    mov eax, [number]

    ; Check if zero
    cmp eax, 0
    jne check_sign
    ; is zero
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_zero
    mov edx, msg_zero_len
    int 0x80
    jmp exit

check_sign:
    ; Check positive/negative
    cmp eax, 0
    jg  is_positive             ; eax > 0

    ; negative
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_neg
    mov edx, msg_neg_len
    int 0x80
    jmp check_parity

is_positive:
    ; positive
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_pos
    mov edx, msg_pos_len
    int 0x80

check_parity:
    ; Determine odd/even (only need to check lowest bit)
    mov eax, [number]
    test eax, 1                 ; Check bit0
    jnz is_odd

    ; even
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_even
    mov edx, msg_even_len
    int 0x80
    jmp exit

is_odd:
    ; odd
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_odd
    mov edx, msg_odd_len
    int 0x80

exit:
    mov eax, 1
    mov ebx, 0
    int 0x80

Conditional jump instructions can only jump to labels within the current code segment; the jump range is usually limited from about 128 bytes (short jump) to 2GB (near jump). NASM automatically selects the appropriate jump encoding.

Other extensions