Assembly Guide — Conditional Execution and Branching
In this tutorial, you will learn about Assembly Guide. We cover key concepts, practical examples, and best practices to help you master this topic.
Assembly conditional execution uses flags set by comparison operations to conditionally jump (jcc) or conditionally move (cmovcc), implementing all decision-making logic.
What You'll Learn
- CMP instruction and flag setting
- Conditional jump instructions
- CMOV (conditional move)
- SETcc (conditional byte)
- Implementing if/else and switch
Why It Matters
Conditional execution is essential for all decision-making in programs. Durga Antivirus Pro uses conditional logic for threat classification.
Real-World Use
Branching in algorithms, error checking, state machines, and optimization decisions.
flowchart LR
A["Conditions"] --> B["CMP & Flags"]
B --> C["Jumps"]
C --> D["CMOV"]
D --> E["If/Else"]
A:::current --> B
style A fill:#2563eb,stroke:#2563eb,color:#fff
style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b
The CMP Instruction
; CMP subtracts operands and sets flags
; It does NOT store the result
cmp rax, rbx
; After CMP:
; ZF = 1 if RAX == RBX
; SF = 1 if RAX - RBX is negative
; CF = 1 if unsigned borrow (RAX < RBX unsigned)
; OF = 1 if signed overflow
; Common patterns:
cmp rax, 0 ; Check if zero
cmp rax, rbx ; Compare two values
test rax, rax ; Check if zero/negative (smaller encoding)
Conditional Jumps
; Signed comparisons
cmp rax, rbx
je equal ; Jump if RAX == RBX
jne not_equal ; Jump if RAX != RBX
jg greater ; Jump if RAX > RBX (signed)
jge ge ; Jump if RAX >= RBX (signed)
jl less ; Jump if RAX < RBX (signed)
jle le ; Jump if RAX <= RBX (signed)
; Unsigned comparisons
ja above ; Jump if RAX > RBX (unsigned)
jae above_equal ; Jump if RAX >= RBX (unsigned)
jb below ; Jump if RAX < RBX (unsigned)
jbe below_equal ; Jump if RAX <= RBX (unsigned)
CMOV (Conditional Move)
; CMOV avoids branch mispredictions
; Available for most condition codes
cmp rax, rbx
cmovg rcx, rdx ; If RAX > RBX, RCX = RDX
cmove rax, rbx ; If RAX == RBX, RAX = RBX
cmovl rax, rcx ; If RAX < RCX, RAX = RCX
; CMOV is useful for:
; - Simple conditional assignments
; - Performance-critical paths
; - Cryptography (no timing variations)
SETcc (Conditional Byte)
; Set byte to 0 or 1 based on condition
; Useful for implementing Boolean results
cmp rax, 0
setz al ; AL = 1 if RAX == 0, else 0
setg al ; AL = 1 if RAX > 0
setl al ; AL = 1 if RAX < 0
; For 64-bit boolean:
cmp rax, rbx
setg al
movzx rax, al ; Zero-extend to 64-bit
If/Else Implementation
; High-level: if (a > b) { x = 1; } else { x = 2; }
cmp rdi, rsi ; Compare a and b
jg .then
; else branch
mov rax, 2
jmp .end
.then:
mov rax, 1
.end:
ret
; Using CMOV (no branches):
xor rax, rax
cmp rdi, rsi
mov rax, 1 ; Default: x = 1
mov rcx, 2
cmovg rax, rcx ; If a <= b, x = 2
Switch Implementation
; Switch typically uses a jump table
switch:
cmp rax, 0 ; Check if in range
jl .default
cmp rax, 3
jg .default
lea rbx, [rel jump_table]
mov rcx, [rbx + rax*8] ; Load address from table
jmp rcx
jump_table:
dq .case0
dq .case1
dq .case2
dq .case3
.case0: mov rax, 10; ret
.case1: mov rax, 20; ret
.case2: mov rax, 30; ret
.case3: mov rax, 40; ret
.default: mov rax, 0; ret
Common Mistakes
1. Using signed jumps for unsigned data
Always use signed jumps (jg, jl) for signed data and unsigned jumps (ja, jb) for unsigned.
2. Forgetting CMP before jump
Jump instructions check flags set by the last flag-modifying instruction. Ensure CMP is the latest.
3. Branch misprediction
Modern CPUs predict branches. Use CMOV or minimize unpredictable branches in hot paths.
4. Missing default in switch
Assembly switch tables need explicit default handling. Out-of-range indices cause jumps to garbage.
5. Confusing TEST and CMP
test rax, rax is like cmp rax, 0 but smaller encoding. Use test for zero/negative checks.
Practice Questions
1. How does CMP work? CMP subtracts the second operand from the first and sets flags without storing the result.
2. When should you use CMOV instead of conditional jumps? When the condition is unpredictable (e.g., sorting random data) and both paths are short.
3. What is the difference between signed and unsigned comparisons? Signed uses jg/jl (considers overflow flag). Unsigned uses ja/jb (considers carry flag).
Challenge: Write assembly that returns the absolute difference between two numbers using CMOV.
FAQ
{{< faq question="Can I chain multiple conditions?" >} Yes. Nest conditional jumps or combine with AND/OR logic using TEST instructions. {{< /faq >}}
{{< faq question="What flags does CMP affect?" >} CMP affects ZF, SF, CF, OF, AF, and PF. The important ones for jumps are ZF, SF, CF, OF. {{< /faq >}}
{{< faq question="Is CMOV always faster than jumps?" >} Not always. CMOV adds data dependency. For predictable branches, jumps are faster. {{< /faq >}}
{{< faq question="How do I implement && (logical AND) in assembly?" >} Evaluate the first condition. If false, jump to the end. If true, evaluate the second condition. {{< /faq >}}
{{< faq question="What is the loop instruction?" >} loop decreases RCX and jumps to label if RCX != 0. Rarely used (slower than manual dec/jnz). {{< /faq >}}
Mini Project
Implement max of three values with CMOV:
; long max3(long a, long b, long c)
; Return max(a, b, c)
max3:
mov rax, rdi ; rax = a
cmp rax, rsi ; compare a, b
cmovl rax, rsi ; if a < b, rax = b
cmp rax, rdx ; compare max, c
cmovl rax, rdx ; if max < c, rax = c
ret
What's Next
Now that you understand conditionals, explore loop constructs for iteration.
| Topic | Description | Link |
|---|---|---|
| Assembly Loops | Loop constructs | {{< ref "08-loops" >}} |
| Assembly Procedures | Function calls | {{< ref "10-procedures" >}} |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro