Quiz Entry - updated: 2026.07.06
How do you trace which register holds which value as you read assembly top-to-bottom?
Keep a running register map: start from the argument registers, update it after every instruction, and assume every caller-saved register is unknown after a call.
Example — trace phase_1:
phase_1:
push %rbx # [rdi=input, rbx=saved]
mov %rdi, %rbx # [rbx=input]
call <phase_init> # [rbx=input, rdi/rsi/rax=unknown]
mov $0x402490, %esi # [rbx=input, esi=expected_str]
mov %rbx, %rdi # [rdi=input, esi=expected_str]
call <strings_not_equal> # [eax=result]
test %eax, %eax # flags set based on result
je 400dbf # if result==0, skip bomb
Practical method:
- Start with known register state (arguments:
%rdi=1st,%rsi=2nd, etc.) - After
mov A, B→ B now holds what A held - After
call→ assume all caller-saved registers are trashed (%rax,%rcx,%rdx,%rsi,%rdi,%r8-%r11). Only callee-saved survive. - After arithmetic (
add,sub,lea, etc.) → destination register has new value
Write it down for complex functions: Use comments like # rdi=input, rbx=count, r12=base_ptr at each step. This is the single most effective technique for understanding assembly.
Go deeper: