AsAssembly · Lesson 5 of 10

Control Flow & Loops

Assembly has no if/else, no for loops. It has unconditional jumps (`jmp`) and conditional jumps that read the FLAGS register. Every higher-level control structure is built from these two primitives.

x86-64 ASM
; Unconditional jump
jmp label           ; jump to label (like goto)

; Conditional jumps — read FLAGS set by cmp/test
; After cmp rax, rbx:
je  label           ; jump if equal       (ZF=1)
jne label           ; jump if not equal   (ZF=0)
jg  label           ; jump if greater     (signed: ZF=0, SF=OF)
jge label           ; jump if >=
jl  label           ; jump if less        (signed: SF≠OF)
jle label           ; jump if <=
ja  label           ; jump if above       (unsigned greater: CF=0, ZF=0)
jb  label           ; jump if below       (unsigned less: CF=1)
jz  label           ; same as je  (jump if zero)
jnz label           ; same as jne (jump if not zero)
js  label           ; jump if sign (SF=1, result negative)

; if (rax > 0) { do something }
test rax, rax       ; set flags from rax
jle  .skip          ; jump if rax <= 0
; ... "then" block ...
.skip:

; if-else
cmp rax, 10
jge .else
; ... "then" block (rax < 10) ...
jmp .end
.else:
; ... "else" block (rax >= 10) ...
.end:
x86-64 ASM
; Loop: sum = 0; for i in 0..9: sum += i
section .text
global _start

_start:
    xor rax, rax        ; rax = 0 (sum)
    xor rcx, rcx        ; rcx = 0 (i)

.loop:
    add rax, rcx        ; sum += i
    inc rcx             ; i++
    cmp rcx, 10
    jl  .loop           ; if i < 10, loop again

    ; rax now holds 45 (0+1+2+...+9)

    mov rdi, rax        ; exit with the sum as status code (visible via $?)
    mov rax, 60
    syscall

; loop instruction — uses rcx as counter (decrement + jnz in one instruction)
; (less common in modern code, but valid)
    mov rcx, 10
.loop2:
    ; ... loop body ...
    loop .loop2         ; rcx--; if rcx != 0 goto .loop2

; Nested loop: 3x3 matrix print (indices only, no actual print here)
    xor r12, r12        ; row = 0
.outer:
    xor r13, r13        ; col = 0
.inner:
    ; do something with r12=row, r13=col
    inc r13
    cmp r13, 3
    jl .inner           ; col < 3
    inc r12
    cmp r12, 3
    jl .outer           ; row < 3
◆ Note
Labels starting with `.` (like `.loop`, `.skip`) are local labels — they're scoped to the enclosing non-local label. This avoids name collisions in large files and is the conventional style in NASM.