← Back to Guide

📋 Quick Reference

Essential tables and diagrams for exam prep

Jump to Section

📦 x86-64 Registers

Register Size Purpose Preserved?
rax 64-bit Return value, arithmetic Caller-saved
rbx 64-bit General purpose Callee-saved
rcx 64-bit 4th argument, counter Caller-saved
rdx 64-bit 3rd argument, remainder Caller-saved
rsi 64-bit 2nd argument Caller-saved
rdi 64-bit 1st argument Caller-saved
rbp 64-bit Base pointer (frame) Callee-saved
rsp 64-bit Stack pointer Special
r8-r9 64-bit 5th, 6th arguments Caller-saved
r12-r15 64-bit General purpose Callee-saved

Register Hierarchy

rax (64-bit): [--------64 bits--------] eax (32-bit): [--32 bits--] ax (16-bit): [16 bits] al (8-bit): [8b] ah (8-bit): [8b]

⚙️ Common Assembly Instructions

Instruction Description Example
mov dst, src Move/copy value mov rax, 42
add dst, src Addition add rax, rcx
sub dst, src Subtraction sub rax, 5
imul src Signed multiply (rax * src → rdx:rax) imul rcx
idiv src Signed divide (rdx:rax / src) idiv rcx
cqo Sign-extend rax → rdx cqo
push src Push to stack (rsp -= 8) push rax
pop dst Pop from stack (rsp += 8) pop rcx
call func Call function call foo
ret Return from function ret
cmp a, b Compare (sets flags) cmp rax, 0
test a, b Bitwise AND (sets flags) test rax, rax
je label Jump if equal (ZF=1) je .L1
jne label Jump if not equal jne .L2
jl / jg Jump if less / greater jl .L3
jmp label Unconditional jump jmp .L4
lea dst, [addr] Load effective address lea rax, [rbp-8]

📚 Stack Machine Instructions

Instruction Description Stack Effect
PUSH value Push constant [...] → [..., value]
ADD Pop 2, push sum [..., a, b] → [..., a+b]
SUB Pop 2, push difference [..., a, b] → [..., a-b]
MUL Pop 2, push product [..., a, b] → [..., a*b]
DIV Pop 2, push quotient [..., a, b] → [..., a/b]
MOD Pop 2, push remainder [..., a, b] → [..., a%b]
LOAD slot Load variable [...] → [..., var]
STORE slot Pop & store to variable [..., val] → [...]
CALL fn, argc Call function [..., args] → [..., result]
RETURN Pop & return [..., val] → exit
JUMP_IF_FALSE lbl Pop, jump if 0 [..., cond] → [...]
JUMP lbl Unconditional jump [...] → [...]

📞 System V x86-64 Calling Convention

Element Details
Arguments (1-6) rdi, rsi, rdx, rcx, r8, r9
Arguments (7+) Pushed on stack (right to left)
Return Value rax
Caller-saved rax, rcx, rdx, rsi, rdi, r8-r11
Callee-saved rbx, rbp, r12-r15
Stack Alignment 16-byte before call
Variable at slot N [rbp - (N+1)*8]

Function Prologue / Epilogue

Prologue

push rbp ; Save old frame mov rbp, rsp ; New frame base sub rsp, N ; Space for locals

Epilogue

mov rsp, rbp ; Restore stack pop rbp ; Restore frame ret ; Return

🎯 Operator Precedence (High to Low)

Level Operators Associativity
1 () grouping N/A
2 - ~ ! unary Right
3 * / % Left
4 + - binary Left
5 < > <= >= Left
6 == != Left
7 && logical AND Left
8 || logical OR Left

🧠 Memory Layout

Stack Frame

Higher addresses
┌──────────────────────┐
│   caller's stack     │
├──────────────────────┤
│   return address     │  ← pushed by call
├──────────────────────┤
│   saved rbp          │  ← rbp points here
├──────────────────────┤
│   param 0  (slot 0)  │  ← [rbp - 8]  (from rdi)
├──────────────────────┤
│   param 1  (slot 1)  │  ← [rbp - 16] (from rsi)
├──────────────────────┤
│   local 0  (slot 2)  │  ← [rbp - 24]
├──────────────────────┤
│   local 1  (slot 3)  │  ← [rbp - 32]
└──────────────────────┘  ← rsp
Lower addresses

Pointer Arithmetic

int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr + 2;

Memory:
┌────┬────┬────┬────┬────┐
│ 10 │ 20 │ 30 │ 40 │ 50 │
└────┴────┴────┴────┴────┘
  ↑         ↑
 arr       ptr

*ptr       = 30  (arr[2])
*(ptr + 1) = 40  (arr[3])
*(ptr - 1) = 20  (arr[1])
ptr[1]     = 40  (same as *(ptr + 1))

Key: ptr + n moves n × sizeof(int) bytes

🔄 Compiler Pipeline

┌──────────────────────────────────────────────────────┐
│  Step 1: LEXER (Lexical Analysis)                    │
│  Breaks source code into tokens                      │
└──────────────────────────────────────────────────────┘
  Input:  fn main() -> int { return 42 }
  Output: [fn, main, (, ), ->, int, {, return, 42, }]
                            ↓
┌──────────────────────────────────────────────────────┐
│  Step 2: PARSER (Syntax Analysis)                    │
│  Builds Abstract Syntax Tree (AST)                   │
└──────────────────────────────────────────────────────┘
  Output: FN_DEF(name="main", body=[RETURN(INTEGER(42))])
                            ↓
┌──────────────────────────────────────────────────────┐
│  Step 3: CODE GENERATOR                              │
│  Generates stack machine instructions                │
└──────────────────────────────────────────────────────┘
  Output: FN main
          PUSH 42
          RETURN
                            ↓
┌──────────────────────────────────────────────────────┐
│  Step 4: ASSEMBLY GENERATOR                          │
│  Converts to x86-64 assembly                         │
└──────────────────────────────────────────────────────┘
  Output: main:
          mov rax, 42
          ret
                            ↓
┌──────────────────────────────────────────────────────┐
│  Step 5: ASSEMBLER + LINKER (nasm + ld)              │
│  Creates executable binary                           │
└──────────────────────────────────────────────────────┘
  Output: ./main (executable)

🐍 Python vs C Comparisons

Variables & Memory

Python

x = 42 # Label to object x = "hello" # Same label, new object # Automatic garbage collection

C

int x = 42; // Memory location x = 100; // Same location // Manual memory management

Strings

Python

s = "hello" len(s) # O(1) s + " world" # Easy concat s == "hello" # Value comparison

C

char *s = "hello"; strlen(s); // O(n) scan strcat(dst, s); // Requires buffer strcmp(s, "hello"); // Returns 0 if equal

Arrays

Python

arr = [1, 2, 3] arr.append(4) # Dynamic sizing len(arr) # Built-in length

C

int arr[3] = {1, 2, 3}; // Fixed size, no append // No built-in length tracking sizeof(arr)/sizeof(arr[0]); // Compile-time only