Skip to content
Comparisons, Jumps, Loops
step 1/5

Reading — step 1 of 5

Learn

~2 min readControl Flow and Memory

Assembly has no if/else or for. Instead: compare two values, then conditional jump based on the result.

cmp and jumps

mov rax, 5
mov rbx, 10
cmp rax, rbx       ; sets flags based on rax - rbx
jl  is_less        ; jump if signed less than
jge is_greater_eq  ; jump if signed >=

cmp a, b sets CPU flags as if computing a - b. The conditional jump tests those flags.

Conditional jump instructions

Equality — sign does not matter:

  • je / jz — equal / zero
  • jne / jnz — not equal / not zero

For signed comparison:

  • jl / jg — less than / greater than
  • jle / jge — less or equal / greater or equal

For unsigned:

  • jb / ja — below / above
  • jbe / jae — below-or-equal / above-or-equal

For zero/sign:

  • js / jns — sign / not-sign
  • jc / jnc — carry / no carry

Unconditional jump

jmp label    ; goto

Loop: count from 0 to 9

section .data
    digit db 0, 10

section .text
    global _start
_start:
    xor rcx, rcx           ; rcx = 0 (counter)
    
loop_start:
    cmp rcx, 10
    jge loop_end
    
    ; convert rcx to ASCII
    mov al, cl
    add al, '0'            ; '0' = 0x30
    mov [digit], al
    
    ; write to stdout
    push rcx               ; preserve rcx across syscall
    mov rax, 1
    mov rdi, 1
    mov rsi, digit
    mov rdx, 2
    syscall
    pop rcx
    
    inc rcx
    jmp loop_start

loop_end:
    mov rax, 60
    xor rdi, rdi
    syscall

The loop instruction (legacy)

x86 has a built-in loop instruction that decrements rcx and jumps if non-zero:

mov rcx, 10
my_loop:
    ; ... body ...
    loop my_loop          ; rcx-- ; if (rcx != 0) jump

It's slower than manual dec/jnz on modern CPUs but more compact in code.

Test bit instruction

test rax, rax     ; AND with itself, sets ZF if zero
jz  is_zero       ; jump if rax was 0

test rax, rax is the canonical way to check if a register is zero.

A pattern: while-not-zero

.loop:
    test rax, rax
    jz .done
    ; ... body ...
    dec rax
    jmp .loop
.done:

The .loop and .done are local labels — visible only within the enclosing global label. Less namespace pollution.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…