Day 2 of 5
⏱ ~60 minutes
Assembly Language in 5 Days — Day 2

Arithmetic, Flags & Control Flow

Assembly programs control flow with conditional jumps based on CPU flags. Today you master arithmetic instructions, the FLAGS register, loops, and function calls using the call/ret convention.

Arithmetic Instructions

ADD, SUB, MUL, DIV, INC, DEC, NEG, AND, OR, XOR, NOT, SHL, SHR are the core arithmetic instructions. MUL (unsigned) and IMUL (signed) multiply RAX by the operand; the 128-bit result goes into RDX:RAX. DIV divides RDX:RAX by the operand; quotient in RAX, remainder in RDX. Shifts (SHL/SHR) are fast multiply/divide by powers of 2.

The FLAGS Register and Conditional Jumps

Arithmetic operations set flags in RFLAGS: ZF (zero), SF (sign), CF (carry), OF (overflow), PF (parity). CMP a, b subtracts b from a and sets flags without storing the result. JE/JZ (jump if equal/zero), JNE (not equal), JL/JG (less/greater, signed), JB/JA (below/above, unsigned). These combine to implement if/else, while loops, and for loops.

The Call Stack and Functions

CALL pushes RIP+1 onto the stack and jumps to the target. RET pops the saved return address into RIP. The System V AMD64 ABI (Linux calling convention): first 6 args in RDI, RSI, RDX, RCX, R8, R9; return value in RAX; callee must preserve RBX, RBP, R12-R15. Build a stack frame with 'push rbp / mov rbp, rsp' at the start and 'pop rbp / ret' at the end.

nasm
; sum.asm: sum integers 1..N using a loop
section .text
    global _start

; int sum(int n) - compute 1+2+...+n
sum:
    push rbp
    mov  rbp, rsp
    xor  rax, rax       ; accumulator = 0
    xor  rcx, rcx       ; counter = 0
.loop:
    inc  rcx            ; counter++
    add  rax, rcx       ; acc += counter
    cmp  rcx, rdi       ; counter == n?
    jne  .loop
    pop  rbp
    ret                 ; return rax

_start:
    mov  rdi, 100       ; n = 100
    call sum            ; result in rax
    ; rax now holds 5050
    mov  rax, 60        ; exit
    xor  rdi, rdi
    syscall
💡
Use GDB or radare2 to step through your assembly instruction by instruction. Run 'gdb ./program', then 'layout asm' for the TUI, 'b _start' to set a breakpoint, 'run' to start, and 'ni' to step.
📝 Day 2 Exercise
Implement a Fibonacci Loop
  1. Write an assembly function that computes the Nth Fibonacci number using a loop
  2. Use RDI for input N and return the result in RAX
  3. Handle edge cases: N=0 returns 0, N=1 returns 1
  4. Call the function from _start with N=10 (answer: 55)
  5. Debug with GDB: step through the loop and watch RAX change at each iteration

Day 2 Summary

  • CMP sets flags without storing results; conditional jumps read those flags
  • MUL/DIV use RDX:RAX as a 128-bit register pair
  • System V AMD64 ABI: args in RDI/RSI/RDX/RCX/R8/R9, return in RAX
  • CALL pushes return address; RET pops it back into RIP
  • Use GDB's 'layout asm' and 'ni' to step through assembly
Challenge

Write a bubble sort in assembly that sorts an array of 8 quadwords (64-bit integers) defined in .data. Print the before and after arrays to stdout.

Finished this lesson?