Essential tables and diagrams for exam prep
| 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 |
| 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] |
| 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 | [...] → [...] |
| 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] |
| 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 |
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
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
┌──────────────────────────────────────────────────────┐
│ 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)