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
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.
| Instruction | Meaning | Flags Checked | Applicable Scenario |
|---|---|---|---|
| JE / JZ | Jump if equal / zero | ZF = 1 | cmp a, bCheck a == b after CMP |
| JNE / JNZ | Jump if not equal / not zero | ZF = 0 | cmp a, bCheck a != b after CMP |
| JG / JNLE | Jump if greater (signed) | ZF=0 and SF=OF | Signed numbers a > b |
| JGE / JNL | Jump if greater or equal (signed) | SF = OF | Signed numbers a >= b |
| JL / JNGE | Jump if less (signed) | SF != OF | Signed numbers a < b |
| JLE / JNG | Jump if less or equal (signed) | ZF=1 or SF!=OF | Signed numbers a <= b |
| JA / JNBE | Jump if above (unsigned) | CF=0 and ZF=0 | Unsigned numbers a > b |
| JAE / JNB | Jump if above or equal (unsigned) | CF = 0 | Unsigned numbers a >= b |
| JB / JNAE | Jump if below (unsigned) | CF = 1 | Unsigned numbers a < b |
| JBE / JNA | Jump if below or equal (unsigned) | CF=1 or ZF=1 | Unsigned 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
; 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
; 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
; 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
; 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
; 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
; 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
Other extensionsConditional 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.