x86-64
registers, the calling convention, and the instructions i actually type. everything is in intel/nasm order, so op dst, src.
jump to registers · calling convention · instructions · addressing · conditions
registers
64 32 16 8 role (sysv)
rax eax ax al return value
rdi edi di dil arg 1
rsi esi si sil arg 2
rdx edx dx dl arg 3 (also 2nd return)
rcx ecx cx cl arg 4
r8 r8d r8w r8b arg 5
r9 r9d r9w r9b arg 6
r10 r10d r10w r10b scratch
r11 r11d r11w r11b scratch
rbx ebx bx bl callee-saved
rbp ebp bp bpl frame pointer (callee-saved)
rsp esp sp spl stack pointer
r12 r12d r12w r12b callee-saved
r13 r13d r13w r13b callee-saved
r14 r14d r14w r14b callee-saved
r15 r15d r15w r15b callee-saved
ripis the instruction pointer andrflagsholds the status flags (zf, sf, cf, of, ...)xmm0toxmm15are the 128-bit sse registers for floats and vectors- legacy
ah, bh, ch, dhalias the high byte of the first four
calling convention (sysv amd64)
linux and macos. windows x64 is different (rcx, rdx, r8, r9).
- integer and pointer args go in
rdi, rsi, rdx, rcx, r8, r9in that order, and the rest go on the stack, pushed right to left - float args go in
xmm0toxmm7 - the return value goes in
rax(rdx:raxfor 128-bit), and floats come back inxmm0 rbx, rbp, rsp, r12, r13, r14, r15are callee-saved, so you have to restore themrax, rcx, rdx, rsi, rdi, r8, r9, r10, r11are caller-saved (scratch)- the stack has to be 16-byte aligned at the
call, and leaf functions get a 128-byte red zone belowrsp - syscalls are different. the number goes in
raxand the args go inrdi, rsi, rdx, r10, r8, r9(see interrupts)
instructions
cmp a, bsets flags fora − b, andtest a, bsets flags fora & bimul/idivare signed andmul/divare unsigned.sarkeeps the sign bit andshrdoesn'tmovzx/movsxzero- or sign-extend, andleadoes address math without touching memory or flags- writing a 32-bit register zeroes the upper half of the 64-bit one, but writing 8 or 16 bits leaves the rest alone
; int add(int a, int b) { return a + b; } (sysv)
add:
lea eax, [rdi + rsi] ; a in edi, b in esi -> eax
ret
addressing modes
- base + index·scale + disp,
[rbx + rcx*4 + 8]with scale ∈ {1, 2, 4, 8} - rip-relative,
[rel label](nasm) or[rip + label]
conditions (jcc after cmp)
- signed compares use
jg(>),jge(≥),jl(<), andjle(≤) - unsigned compares use
ja(>),jae(≥),jb(<), andjbe(≤) - flag jumps are
js/jns(sign),jo/jno(overflow), andjc/jnc(carry)