π Topic 5: Conditional Jumps
Master conditional execution - the foundation of if/else logic in assembly.
Overview
Jumps are how you control program flow in assembly. They let you:
- Implement if/else statements
- Create loops
- Handle different cases
- Skip code sections
- Build complex logic
Types of jumps:
- π Unconditional jumps (always jump)
- π― Conditional jumps (jump based on flags)
Part 1: How Jumps Work
The Instruction Pointer
The RIP (Instruction Pointer) register always points to the next instruction to execute.
Normal execution (no jumps):
βββββββββββββββββββ
β mov rax, 10 β β RIP here
β add rax, 5 β β RIP moves here next
β mov rbx, rax β β Then here
β ret β β Finally here
βββββββββββββββββββ
With a jump:
βββββββββββββββββββ
β mov rax, 10 β β RIP here
β jmp skip β β Jump changes RIP
β add rax, 5 β (skipped!)
β skip: β β RIP jumps here
β mov rbx, rax β
βββββββββββββββββββ
Labels
Labels are markers in your code that jumps can target:
section .text
global _start
_start: ; Label marking program start
mov rax, 10
jmp continue ; Jump to 'continue' label
; This code is skipped
mov rax, 99
continue: ; Label marking jump target
mov rbx, rax ; RBX = 10 (not 99)
; Exit
mov rax, 60
xor rdi, rdi
syscall
Label rules:
- Can contain letters, numbers, underscore, dot
- Must start with letter, underscore, or dot
- Case-sensitive
- Followed by colon
:when defined - No colon when referenced in jumps
Part 2: Unconditional Jumps
JMP - Jump Always
jmp label ; Always jump to label
Examples:
; Simple jump
jmp end_program
mov rax, 100 ; Skipped!
end_program:
; Continues here
; Jump forward
mov rax, 10
jmp skip_error
mov rax, -1 ; Error code (skipped)
skip_error:
; Normal flow
; Jump backward (loop)
start_loop:
dec rcx
cmp rcx, 0
jne start_loop ; Jump back to start_loop
Short vs Near vs Far Jumps
; Short jump (2 bytes, offset -128 to +127 bytes)
jmp short nearby_label
; Near jump (5 bytes, offset Β±2GB)
jmp near far_label
jmp far_label ; Default is near
; Far jump (different code segment, rarely used)
jmp far segment:offset
Usually: Let NASM choose automatically. It picks the shortest encoding.
Part 3: Conditional Jumps
Conditional jumps check CPU flags and jump only if conditions are met.
Jump Mnemonic Format
J + condition
Examples:
JE = Jump if Equal
JNE = Jump if Not Equal
JG = Jump if Greater
JL = Jump if Less
All Conditional Jumps
ββββββββββββββ¬ββββββββββββββββββββββ¬βββββββββββββββββββββ
β Mnemonic β Meaning β Condition β
ββββββββββββββΌββββββββββββββββββββββΌβββββββββββββββββββββ€
β JE / JZ β Jump if Equal/Zero β ZF = 1 β
β JNE / JNZ β Jump if Not Equal β ZF = 0 β
ββββββββββββββΌββββββββββββββββββββββΌβββββββββββββββββββββ€
β JS β Jump if Sign β SF = 1 β
β JNS β Jump if Not Sign β SF = 0 β
ββββββββββββββΌββββββββββββββββββββββΌβββββββββββββββββββββ€
β JC β Jump if Carry β CF = 1 β
β JNC β Jump if Not Carry β CF = 0 β
ββββββββββββββΌββββββββββββββββββββββΌβββββββββββββββββββββ€
β JO β Jump if Overflow β OF = 1 β
β JNO β Jump if Not Overflowβ OF = 0 β
ββββββββββββββΌββββββββββββββββββββββΌβββββββββββββββββββββ€
β JP / JPE β Jump if Parity Even β PF = 1 β
β JNP / JPO β Jump if Parity Odd β PF = 0 β
ββββββββββββββ΄ββββββββββββββββββββββ΄βββββββββββββββββββββ
Signed Comparison Jumps (After CMP)
ββββββββββ¬ββββββββββββββββββββββ¬ββββββββββββββββββββββββ
β Jump β Meaning β Condition β
ββββββββββΌββββββββββββββββββββββΌββββββββββββββββββββββββ€
β JE β Jump if Equal β ZF = 1 β
β JNE β Jump if Not Equal β ZF = 0 β
β JG β Jump if Greater β ZF = 0 AND SF = OF β
β JGE β Jump if β₯ β SF = OF β
β JL β Jump if Less β SF β OF β
β JLE β Jump if β€ β ZF = 1 OR SF β OF β
ββββββββββ΄ββββββββββββββββββββββ΄ββββββββββββββββββββββββ
Unsigned Comparison Jumps (After CMP)
ββββββββββ¬ββββββββββββββββββββββ¬ββββββββββββββββββββββββ
β Jump β Meaning β Condition β
ββββββββββΌββββββββββββββββββββββΌββββββββββββββββββββββββ€
β JE β Jump if Equal β ZF = 1 β
β JNE β Jump if Not Equal β ZF = 0 β
β JA β Jump if Above β CF = 0 AND ZF = 0 β
β JAE β Jump if β₯ β CF = 0 β
β JB β Jump if Below β CF = 1 β
β JBE β Jump if β€ β CF = 1 OR ZF = 1 β
ββββββββββ΄ββββββββββββββββββββββ΄ββββββββββββββββββββββββ
Aliases (Same Instruction, Different Name)
JE = JZ (Equal = Zero)
JNE = JNZ (Not Equal = Not Zero)
JA = JNBE (Above = Not Below or Equal)
JAE = JNB (Above or Equal = Not Below)
JB = JNAE (Below = Not Above or Equal)
JBE = JNA (Below or Equal = Not Above)
JG = JNLE (Greater = Not Less or Equal)
JGE = JNL (Greater or Equal = Not Less)
JL = JNGE (Less = Not Greater or Equal)
JLE = JNG (Less or Equal = Not Greater)
Part 4: Using Conditional Jumps
Basic Pattern
1. Perform comparison (CMP, TEST, or arithmetic)
2. Check flags with conditional jump
3. Execute code based on result
Equality Check
; if (rax == 42) goto equal_handler
cmp rax, 42
je equal_handler ; Jump if equal
; Not equal path
mov rbx, 0
jmp done
equal_handler:
; Equal path
mov rbx, 1
done:
Inequality Check
; if (rax != 42) goto not_equal
cmp rax, 42
jne not_equal ; Jump if not equal
; Equal path
mov rbx, 1
jmp done
not_equal:
; Not equal path
mov rbx, 0
done:
Greater Than (Signed)
; if (rax > 10) goto greater
cmp rax, 10
jg greater ; Jump if rax > 10 (signed)
; Less than or equal path
mov rbx, 0
jmp done
greater:
; Greater path
mov rbx, 1
done:
Less Than (Signed)
; if (rax < 0) goto negative
cmp rax, 0
jl negative ; Jump if rax < 0 (signed)
; Positive or zero path
mov rbx, 0
jmp done
negative:
; Negative path
mov rbx, 1
done:
Above (Unsigned)
; if (rax > 100) goto above [unsigned comparison]
cmp rax, 100
ja above ; Jump if rax > 100 (unsigned)
; Below or equal path
mov rbx, 0
jmp done
above:
; Above path
mov rbx, 1
done:
Part 5: If/Else in Assembly
Simple If Statement
C Code:
if (x == 10) {
y = 100;
}
Assembly:
; if (rax == 10) rbx = 100
cmp rax, 10
jne skip_if ; Jump if not equal (skip the if body)
mov rbx, 100 ; If body
skip_if:
; Continue...
If-Else Statement
C Code:
if (x > 5) {
y = 1;
} else {
y = 0;
}
Assembly:
; if (rax > 5) rbx = 1, else rbx = 0
cmp rax, 5
jle else_branch ; Jump if less or equal
; If true branch
mov rbx, 1
jmp end_if
else_branch:
; Else branch
mov rbx, 0
end_if:
; Continue...
If-Else If-Else
C Code:
if (x < 0) {
result = -1;
} else if (x > 0) {
result = 1;
} else {
result = 0;
}
Assembly:
; Sign function: sign(rax) -> rbx
cmp rax, 0
jl negative ; If x < 0
jg positive ; Else if x > 0
; Else (x == 0)
mov rbx, 0
jmp done
negative:
mov rbx, -1
jmp done
positive:
mov rbx, 1
done:
; Continue...
Nested If Statements
C Code:
if (x > 0) {
if (x < 10) {
result = 1;
}
}
Assembly:
; if (rax > 0 && rax < 10) rbx = 1
cmp rax, 0
jle skip_outer ; Skip if not > 0
cmp rax, 10
jge skip_inner ; Skip if not < 10
mov rbx, 1 ; Both conditions true
skip_inner:
skip_outer:
; Continue...
Part 6: Loops with Jumps
While Loop
C Code:
while (count > 0) {
sum += count;
count--;
}
Assembly:
; while (rcx > 0) { rax += rcx; rcx--; }
while_start:
cmp rcx, 0
jle while_end ; Exit if rcx <= 0
add rax, rcx ; sum += count
dec rcx ; count--
jmp while_start ; Loop back
while_end:
; Continue...
Do-While Loop
C Code:
do {
sum += count;
count--;
} while (count > 0);
Assembly:
; do { rax += rcx; rcx--; } while (rcx > 0)
do_start:
add rax, rcx ; sum += count
dec rcx ; count--
cmp rcx, 0
jg do_start ; Loop if rcx > 0
; Continue...
For Loop
C Code:
for (i = 0; i < 10; i++) {
sum += i;
}
Assembly:
; for (rcx = 0; rcx < 10; rcx++) { rax += rcx; }
xor rcx, rcx ; i = 0
for_start:
cmp rcx, 10
jge for_end ; Exit if i >= 10
add rax, rcx ; sum += i
inc rcx ; i++
jmp for_start
for_end:
; Continue...
Loop with Break
C Code:
while (1) {
if (count == 0) break;
sum += count;
count--;
}
Assembly:
; while (1) { if (rcx == 0) break; rax += rcx; rcx--; }
infinite_loop:
cmp rcx, 0
je loop_break ; Break if count == 0
add rax, rcx
dec rcx
jmp infinite_loop
loop_break:
; Continue after loop...
Loop with Continue
C Code:
for (i = 0; i < 10; i++) {
if (i == 5) continue;
sum += i;
}
Assembly:
; for (rcx = 0; rcx < 10; rcx++) { if (rcx == 5) continue; rax += rcx; }
xor rcx, rcx
loop_start:
cmp rcx, 10
jge loop_end
cmp rcx, 5
je continue_point ; Skip to next iteration
add rax, rcx ; sum += i
continue_point:
inc rcx
jmp loop_start
loop_end:
; Continue...
Part 7: Special Loop Instructions
LOOP - Loop with RCX Counter
loop label ; Decrement RCX, jump if RCX != 0
Equivalent to:
dec rcx
jnz label
Example:
; Loop 10 times
mov rcx, 10
loop_start:
; ... do something ...
loop loop_start ; Decrements RCX, loops if RCX != 0
; RCX is now 0
Limitations:
- Only works with RCX
- Canβt check other conditions
- No way to break early without jumping
When to use:
- Simple counted loops
- When RCX counter is convenient
- Short, simple loop bodies
When not to use:
- Complex loop conditions
- Need to preserve RCX
- Need early exit/break
LOOPcc Variants
loope label ; Loop if equal (ZF = 1) and RCX != 0
loopne label ; Loop if not equal (ZF = 0) and RCX != 0
loopz label ; Same as loope
loopnz label ; Same as loopne
Example:
; Search for zero in array
mov rcx, array_size
mov rsi, array
search_loop:
cmp byte [rsi], 0
loopne search_loop ; Continue if not zero and RCX != 0
; Either found zero or reached end
Rarely used in modern code - explicit comparisons are clearer.
Part 8: Practical Examples
Example 1: Find Maximum
C Equivalent:
#include <stdint.h>
int main() {
int32_t numbers[] = {15, 42, 7, 89, 23, 56};
int32_t count = 6;
int32_t max = numbers[0];
for (int32_t i = 1; i < count; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
// max = 89
return 0;
}
Assembly:
section .data
numbers dd 15, 42, 7, 89, 23, 56
count equ 6
section .bss
max resd 1
section .text
global _start
_start:
; Find maximum value in array
mov eax, [numbers] ; max = numbers[0]
mov ecx, 1 ; i = 1
find_max_loop:
cmp ecx, count
jge found_max ; Exit if i >= count
mov edx, [numbers + rcx*4]
cmp eax, edx
jge skip_update ; Skip if max >= numbers[i]
mov eax, edx ; max = numbers[i]
skip_update:
inc ecx
jmp find_max_loop
found_max:
mov [max], eax ; Store result (89)
; Exit
mov rax, 60
xor rdi, rdi
syscall
Example 2: String Length
C Equivalent:
#include <stdint.h>
size_t my_strlen(const char *str) {
size_t length = 0;
while (str[length] != '\0') {
length++;
}
return length;
}
int main() {
const char *string = "Hello, World!";
size_t length = my_strlen(string);
// length = 13
return length;
}
Assembly:
section .data
string db "Hello, World!", 0
section .text
global _start
_start:
; Calculate string length
mov rsi, string ; Pointer to string
xor rcx, rcx ; Length = 0
strlen_loop:
cmp byte [rsi + rcx], 0 ; Check for null terminator
je strlen_done ; Exit if found null
inc rcx ; Length++
jmp strlen_loop
strlen_done:
; RCX contains length (13)
; Exit
mov rax, 60
mov rdi, rcx ; Exit with length as code
syscall
Example 3: Count Set Bits (Population Count)
C Equivalent:
#include <stdint.h>
int popcount(uint64_t value) {
int count = 0;
while (value != 0) {
if (value & 1) {
count++;
}
value >>= 1; // Shift right by 1
}
return count;
}
int main() {
uint64_t value = 0b10110101;
int count = popcount(value);
// count = 5 (five 1-bits)
return count;
}
Assembly:
section .text
global _start
_start:
; Count set bits in RAX
mov rax, 0b10110101 ; Test value
xor rcx, rcx ; count = 0
count_bits_loop:
test rax, rax
jz count_done ; Exit if no bits left
test rax, 1 ; Check lowest bit
jz skip_count
inc rcx ; Count if set
skip_count:
shr rax, 1 ; Shift to next bit
jmp count_bits_loop
count_done:
; RCX contains count (5 bits set)
; Exit
mov rax, 60
mov rdi, rcx
syscall
Example 4: Binary Search
C Equivalent:
#include <stdint.h>
int binary_search(int32_t *array, int32_t size, int32_t target) {
int32_t left = 0;
int32_t right = size;
while (left < right) {
int32_t mid = (left + right) / 2;
if (array[mid] == target) {
return mid; // Found at index mid
} else if (array[mid] < target) {
left = mid + 1; // Search right half
} else {
right = mid; // Search left half
}
}
return -1; // Not found
}
int main() {
int32_t array[] = {1, 3, 5, 7, 9, 11, 13, 15};
int32_t size = 8;
int32_t target = 7;
int32_t index = binary_search(array, size, target);
// index = 3 (found at position 3)
return index;
}
Assembly:
section .data
; Sorted array
array dd 1, 3, 5, 7, 9, 11, 13, 15
array_size equ 8
target dd 7
section .text
global _start
_start:
; Binary search for target
xor rcx, rcx ; left = 0
mov rdx, array_size ; right = size
mov edi, [target] ; value to find
binary_search:
cmp rcx, rdx
jge not_found ; Exit if left >= right
; mid = (left + right) / 2
mov rax, rcx
add rax, rdx
shr rax, 1 ; Divide by 2
; Compare array[mid] with target
mov esi, [array + rax*4]
cmp esi, edi
je found ; Found!
jl search_right ; array[mid] < target
; Search left half
mov rdx, rax ; right = mid
jmp binary_search
search_right:
; Search right half
lea rcx, [rax + 1] ; left = mid + 1
jmp binary_search
found:
; Found at index RAX
mov rdi, rax
jmp exit_program
not_found:
; Not found
mov rdi, -1
exit_program:
mov rax, 60
syscall
Example 5: FizzBuzz
section .data
fizz db "Fizz", 10
fizz_len equ $ - fizz
buzz db "Buzz", 10
buzz_len equ $ - buzz
fizzbuzz db "FizzBuzz", 10
fizzbuzz_len equ $ - fizzbuzz
section .text
global _start
_start:
mov rcx, 1 ; counter = 1
fizzbuzz_loop:
cmp rcx, 100
jg fizzbuzz_end ; Exit if counter > 100
; Check if divisible by 15
mov rax, rcx
xor rdx, rdx
mov rbx, 15
div rbx
test rdx, rdx
jz print_fizzbuzz ; Divisible by 15
; Check if divisible by 3
mov rax, rcx
xor rdx, rdx
mov rbx, 3
div rbx
test rdx, rdx
jz print_fizz ; Divisible by 3
; Check if divisible by 5
mov rax, rcx
xor rdx, rdx
mov rbx, 5
div rbx
test rdx, rdx
jz print_buzz ; Divisible by 5
; Print number (simplified - just skip)
jmp next_iteration
print_fizzbuzz:
mov rax, 1
mov rdi, 1
mov rsi, fizzbuzz
mov rdx, fizzbuzz_len
syscall
jmp next_iteration
print_fizz:
mov rax, 1
mov rdi, 1
mov rsi, fizz
mov rdx, fizz_len
syscall
jmp next_iteration
print_buzz:
mov rax, 1
mov rdi, 1
mov rsi, buzz
mov rdx, buzz_len
syscall
next_iteration:
inc rcx
jmp fizzbuzz_loop
fizzbuzz_end:
mov rax, 60
xor rdi, rdi
syscall
Part 9: Optimization Tips
Invert Conditions to Reduce Jumps
; β Less efficient (2 jumps in common case)
cmp rax, 10
je equal
mov rbx, 0
jmp done
equal:
mov rbx, 1
done:
; β
More efficient (1 jump in common case)
cmp rax, 10
jne not_equal
mov rbx, 1
jmp done
not_equal:
mov rbx, 0
done:
Place Common Case First
; If rax is usually not zero:
test rax, rax
jnz common_case ; Taken most often (predicted taken)
; Rare case
jmp done
common_case:
; Common case
done:
Avoid Jumping Over Single Instructions
; β Inefficient
test rax, rax
jz skip
inc rbx
skip:
; β
Use conditional move (if appropriate)
test rax, rax
cmovnz rbx, some_value ; Only if rbx = some_value needed
Short Jumps When Possible
NASM automatically chooses, but be aware:
; Short jump: 2 bytes (offset -128 to +127)
jmp short nearby
; Near jump: 5 bytes (offset Β±2GB)
jmp near far_away
Keep frequently executed loops small to fit in instruction cache.
Part 10: Common Patterns
Pattern 1: Early Exit/Guard Clause
; Check precondition and exit early
test rax, rax
jz error_null_pointer ; Exit early if invalid
; Normal processing continues...
Pattern 2: Switch/Case
; switch (rax) { case 0: ..., case 1: ..., default: ... }
cmp rax, 0
je case_0
cmp rax, 1
je case_1
cmp rax, 2
je case_2
jmp default_case
case_0:
; Handle case 0
jmp end_switch
case_1:
; Handle case 1
jmp end_switch
case_2:
; Handle case 2
jmp end_switch
default_case:
; Handle default
end_switch:
Pattern 3: Jump Table (Efficient Switch)
section .data
jump_table dq case_0, case_1, case_2
section .text
; switch (rax) using jump table
cmp rax, 2
ja default_case ; Out of range
jmp [jump_table + rax*8]
case_0:
; Handle case 0
jmp done
case_1:
; Handle case 1
jmp done
case_2:
; Handle case 2
jmp done
default_case:
; Handle default
done:
Pattern 4: State Machine
; Simple state machine
state_loop:
cmp byte [state], 0
je state_0
cmp byte [state], 1
je state_1
cmp byte [state], 2
je state_2
jmp error_invalid_state
state_0:
; Process state 0
; Update state
jmp state_loop
state_1:
; Process state 1
jmp state_loop
state_2:
; Final state
jmp exit
error_invalid_state:
; Handle error
exit:
β Practice Exercises
Exercise 1: Absolute Value
Implement abs(rax) using conditional jumps.
Solution
```nasm ; abs(rax) -> rax test rax, rax jns already_positive ; Jump if not sign (positive) neg rax already_positive: ; RAX now contains absolute value ```Exercise 2: Clamp Function
Clamp RAX to range [min, max]. If RAX < min, set to min. If RAX > max, set to max. min = 10, max = 100
Solution
```nasm ; Clamp rax to [10, 100] cmp rax, 10 jge check_max ; RAX >= 10, check upper bound mov rax, 10 ; RAX < 10, set to 10 jmp done check_max: cmp rax, 100 jle done ; RAX <= 100, already in range mov rax, 100 ; RAX > 100, set to 100 done: ; RAX is now clamped to [10, 100] ```Exercise 3: Count Down Loop
Write a loop that counts from 10 down to 1, summing the values in RAX.
Solution
```nasm xor rax, rax ; sum = 0 mov rcx, 10 ; counter = 10 countdown_loop: add rax, rcx ; sum += counter dec rcx ; counter-- jnz countdown_loop ; Loop if counter != 0 ; RAX = 55 (1+2+3+...+10) ```Exercise 4: Linear Search
Search for value 42 in an array of 10 numbers. Return index in RAX or -1 if not found.
Solution
```nasm section .data array dd 10, 5, 42, 7, 3, 42, 9, 1, 8, 6 count equ 10 section .text xor rcx, rcx ; index = 0 search_loop: cmp rcx, count jge not_found ; Reached end cmp dword [array + rcx*4], 42 je found ; Found it! inc rcx jmp search_loop found: mov rax, rcx ; Return index jmp done not_found: mov rax, -1 ; Return -1 done: ```Exercise 5: Is Prime?
Check if RAX is a prime number. Set RBX = 1 if prime, 0 if not. (Assume RAX >= 2)
Solution
```nasm ; Check if rax is prime cmp rax, 2 je is_prime ; 2 is prime ; Check if even test rax, 1 jz not_prime ; Even numbers (except 2) not prime ; Check odd divisors from 3 to sqrt(rax) mov rbx, 3 check_divisor: ; Check if rbx * rbx > rax mov rcx, rbx imul rcx, rcx cmp rcx, rax jg is_prime ; No divisors found, is prime ; Check if rax % rbx == 0 mov rdx, rax push rax mov rax, rdx xor rdx, rdx div rbx test rdx, rdx pop rax jz not_prime ; Found divisor, not prime add rbx, 2 ; Next odd number jmp check_divisor is_prime: mov rbx, 1 jmp done not_prime: mov rbx, 0 done: ```π Quick Reference
Unconditional Jump
jmp label ; Always jump
Equality Jumps
je/jz label ; Jump if equal/zero (ZF=1)
jne/jnz label ; Jump if not equal/zero (ZF=0)
Signed Comparisons
jg label ; Jump if greater (signed)
jge label ; Jump if greater or equal
jl label ; Jump if less (signed)
jle label ; Jump if less or equal
Unsigned Comparisons
ja label ; Jump if above (unsigned)
jae label ; Jump if above or equal
jb label ; Jump if below (unsigned)
jbe label ; Jump if below or equal
Single Flag Tests
js label ; Jump if sign (negative)
jns label ; Jump if not sign (positive/zero)
jc label ; Jump if carry
jnc label ; Jump if not carry
jo label ; Jump if overflow
jno label ; Jump if not overflow
Loop Instructions
loop label ; dec rcx; jnz label
loope/loopz label ; Loop if equal and rcx!=0
loopne/loopnz label ; Loop if not equal and rcx!=0
π― Knowledge Check
Before moving to Topic 6, verify you understand:
- β How RIP controls program flow
- β Unconditional jumps (JMP)
- β Conditional jumps based on flags
- β Signed vs unsigned comparison jumps
- β Implementing if/else statements
- β Building loops with jumps
- β When to use LOOP instruction
- β Jump optimization techniques
π Excellent! You now master conditional jumps and control flow!
Next: Topic 6: Loops (coming soon)
| β Previous Topic | Back to Main | Next Topic β |