Control Flow in Assembly
Control flow in assembly language is managed through jumps, conditional branches, and loops. Unlike high-level languages that have structured control statements, assembly uses simple jump instructions to alter program flow.
Unconditional Jumps
The JMP
instruction transfers control to another part of the program unconditionally.
section .text
global _start
_start:
mov eax, 10
jmp skip ; Jump to 'skip' label
mov eax, 20 ; This instruction is skipped
skip:
; EAX contains 10 here
Conditional Jumps
Conditional jumps transfer control based on the state of processor flags. These are typically used after
comparison (CMP
) or test (TEST
) instructions.
Common Conditional Jumps
Instruction | Description | Condition |
---|---|---|
JE/JZ | Jump if equal/zero | ZF = 1 |
JNE/JNZ | Jump if not equal/not zero | ZF = 0 |
JG/JNLE | Jump if greater/not less or equal | ZF = 0 and SF = OF |
JGE/JNL | Jump if greater or equal/not less | SF = OF |
JL/JNGE | Jump if less/not greater or equal | SF ≠ OF |
JLE/JNG | Jump if less or equal/not greater | ZF = 1 or SF ≠ OF |
JC/JB/JNAE | Jump if carry/borrow/not above or equal | CF = 1 |
JNC/JNB/JAE | Jump if no carry/not borrow/above or equal | CF = 0 |
Conditional Jump Example
section .text
global _start
_start:
mov eax, 15
mov ebx, 20
cmp eax, ebx ; Compare EAX and EBX
jg greater ; Jump if EAX > EBX
; Else case
mov ecx, ebx ; ECX = EBX
jmp end
greater:
mov ecx, eax ; ECX = EAX
end:
; ECX contains the larger value
Loops
Loops in assembly are implemented using conditional jumps. The LOOP
instruction provides
a convenient way to implement counted loops.
Simple Loop
section .text
global _start
_start:
mov ecx, 5 ; Loop counter
xor eax, eax ; Clear EAX (sum = 0)
loop_start:
add eax, ecx ; Add counter to sum
dec ecx ; Decrement counter
jnz loop_start ; Jump if not zero
; EAX now contains 5+4+3+2+1 = 15
LOOP Instruction
section .text
global _start
_start:
mov ecx, 5 ; Loop counter
xor eax, eax ; Clear EAX (sum = 0)
loop_start:
add eax, ecx ; Add counter to sum
loop loop_start ; Decrement ECX and loop if not zero
; EAX now contains 5+4+3+2+1 = 15
Nested Loops
Nested loops require saving and restoring the outer loop counter.
section .text
global _start
_start:
mov ecx, 3 ; Outer loop counter
outer_loop:
push ecx ; Save outer counter
mov ecx, 2 ; Inner loop counter
inner_loop:
; Do something here
loop inner_loop
pop ecx ; Restore outer counter
loop outer_loop
Flags Register
Conditional jumps depend on the flags register (EFLAGS). Important flags include:
- ZF (Zero Flag): Set when result is zero
- SF (Sign Flag): Set when result is negative
- CF (Carry Flag): Set on unsigned overflow
- OF (Overflow Flag): Set on signed overflow
Comparison Instructions
These instructions set flags without modifying operands.
CMP - Compare
cmp eax, ebx ; Sets flags as if (EAX - EBX)
TEST - Logical Compare
test eax, eax ; Sets ZF if EAX is zero
test ebx, 1 ; Check if least significant bit is set
Conditional Move
Modern x86 processors support conditional move instructions that can avoid branches.
section .text
global _start
_start:
mov eax, 15
mov ebx, 20
cmp eax, ebx
cmovg ecx, eax ; Move EAX to ECX if greater
cmovle ecx, ebx ; Move EBX to ECX if less or equal
Switch/Case Implementation
Switch statements can be implemented using a jump table.
section .data
jump_table dd case0, case1, case2, case3
section .text
global _start
_start:
mov eax, 2 ; Case selector
cmp eax, 3
ja default ; Jump if above 3
jmp [jump_table + eax*4]
case0:
; Case 0 code
jmp end
case1:
; Case 1 code
jmp end
case2:
; Case 2 code
jmp end
case3:
; Case 3 code
jmp end
default:
; Default case code
end:
; Continue execution
Practical Examples
Example 1: Finding Maximum Value
section .data
numbers dd 10, 20, 15, 25, 5
count equ 5
section .text
global _start
_start:
mov esi, numbers ; Pointer to array
mov ecx, count ; Number of elements
mov eax, [esi] ; Initialize max with first element
find_max:
cmp eax, [esi] ; Compare current max with array element
jge not_greater ; Jump if current max is greater or equal
mov eax, [esi] ; Update max
not_greater:
add esi, 4 ; Move to next element
loop find_max ; Repeat until ECX = 0
; EAX now contains the maximum value (25)
Example 2: Count Even Numbers
section .data
numbers dd 11, 22, 33, 44, 55
count equ 5
section .text
global _start
_start:
mov esi, numbers ; Pointer to array
mov ecx, count ; Number of elements
xor ebx, ebx ; EBX = even count (0)
count_evens:
test dword [esi], 1 ; Test least significant bit
jnz odd ; Jump if odd
inc ebx ; Increment even count
odd:
add esi, 4 ; Move to next element
loop count_evens ; Repeat until ECX = 0
; EBX now contains the count of even numbers (2)
Optimization Tips
- Use
TEST reg, reg
instead ofCMP reg, 0
for zero checks - Arrange conditional jumps so the most likely path falls through
- Consider using conditional moves instead of branches when possible
- Unroll small loops to reduce branch overhead
Next Steps
Now that you understand control flow, you can learn about: