x86_64 NASM Assembly Quick Reference (“Cheat Sheet”)¶
Here’s the full list of ordinary integer x86 registers. The 64 bit registers are shown in red. “Scratch” registers any function is allowed to overwrite, and use for anything you want without asking anybody. “Preserved” registers have to be put back (“save” the register) if you use them.
Name |
Notes |
Type |
64-bit–make-br–long |
32-bit–make-br–int |
16-bit–make-br–short |
8-bit–make-br–char |
rax |
Values are returned from functions in this register. |
scratch |
rax |
eax |
ax |
ah and al |
rcx |
Typical scratch register. Some instructions also use it as a counter. |
scratch |
rcx |
ecx |
cx |
ch and cl |
rdx |
Scratch register. |
scratch |
rdx |
edx |
dx |
dh and dl |
rbx–make-br– |
Preserved register: don’t use it without saving it! |
preserved |
rbx |
ebx |
bx |
bh and bl |
rsp–make-br– |
The stack pointer. Points to the top of the stack (details coming soon!)–make-br– |
preserved |
rsp |
esp |
sp |
spl |
rbp–make-br– |
Preserved register. Sometimes used to store the old value of the stack pointer, or the “base”. |
preserved |
rbp |
ebp |
bp |
bpl |
rsi |
Scratch register used to pass function argument #2 in 64-bit Linux. In 64-bit Windows, a preserved register. |
scratch |
rsi |
esi |
si |
sil |
rdi |
Scratch register and function argument #1 in 64-bit Linux. In 64-bit Windows, a preserved register. |
scratch |
rdi |
edi |
di |
dil |
r8 |
Scratch register. These were added in 64-bit mode, so they have numbers, not names. |
scratch |
r8 |
r8d |
r8w |
r8b |
r9 |
Scratch register. |
scratch |
r9 |
r9d |
r9w |
r9b |
r10 |
Scratch register. |
scratch |
r10 |
r10d |
r10w |
r10b |
r11 |
Scratch register. |
scratch |
r11 |
r11d |
r11w |
r11b |
r12–make-br– |
Preserved register. You can use it, but you need to save and restore it.–make-br– |
preserved |
r12 |
r12d |
r12w |
r12b |
r13–make-br– |
Preserved register. |
preserved |
r13 |
r13d |
r13w |
r13b |
r14–make-br– |
Preserved register. |
preserved |
r14 |
r14d |
r14w |
r14b |
r15–make-br– |
Preserved register. |
preserved |
r15 |
r15d |
r15w |
r15b |
A 64 bit linux machine passes function parameters in rdi, rsi, rdx, rcx, r8, and r9. Any additional parameters get pushed on the stack. OS X in 64 bit uses the same parameter scheme. Example function call:
extern putchar
mov rdi,'H' ; function parameter: one char to print
call putchar
Windows in 64 bit is quite different:
Win64 function parameters go in registers rcx, rdx, r8, and r9.
Win64 functions assume you’ve allocated 32 bytes of stack space to store the four parameter registers, plus another 8 bytes to align the stack to a 16-byte boundary.
sub rsp,32+8; parameter area, and stack alignment extern putchar mov rcx,'H' ; function parameter: one char to print call putchar add rsp,32+8 ; clean up stack
Win64 treats the registers rdi and rsi as preserved.
Some function such as printf only get linked if they’re called from C/C++ code, so to call printf from assembly, you need to include at least one call to printf from the C/C++ too.
If you use the MASM assembler, memory accesses must include “PTR”, like “DWORD PTR [rsp]”.
See NASM assembly in 64-bit Windows in Visual Studio to make linking work.
In `32 bit mode, <>`__parameters are passed by pushing them onto the stack in reverse order, so the function’s first parameter is on top of the stack before making the call. In 32-bit mode Windows and OS X compilers also seem to add an underscore before the name of a user-defined function, so if you call a function foo from C/C++, you need to define it in assembly as “_foo”.
–make-br–You can convert values between different register sizes using different mov instructions:
Source Size
64 bit rcx
32 bit ecx
16 bit cx
8 bit cl
Notes
64 bit rax
mov rax,rcx
movsxd rax,ecx
movsx rax,cx
movsx rax,cl
Writes to whole register
32 bit eax
mov eax,ecx
mov eax,ecx
movsx eax,cx
movsx eax,cl
Top half of destination gets zeroed
16 bit ax
mov ax,cx
mov ax,cx
mov ax,cx
movsx ax,cl
Only affects low 16 bits, rest unchanged.
8 bit al
mov al,cl
mov al,cl
mov al,cl
mov al,cl
Only affects low 8 bits, rest unchanged.
–make-br–Memory access:¶
C/C++ datatype |
Bits |
Bytes |
Register |
Access memory |
Allocate memory |
char |
8 |
1 |
al |
BYTE [ptr] |
db |
short |
16 |
2 |
ax |
WORD [ptr] |
dw |
int |
32 |
4 |
eax |
DWORD [ptr] |
dd |
long |
64 |
8 |
rax |
QWORD [ptr] |
dq |
Instructions (basically identical to 32-bit x86)¶
For gory instruction set details, read this per-instruction reference, or the full Intel PDFs: part 1 (A-M) and part 2 (N-Z).
Mnemonic |
Purpose |
Examples |
mov dest,src |
Move data between registers, load immediate data into registers, move data between registers and memory. |
mov rax,4 ; Load constant into rax–make-br–mov rdx,rax ; Copy rax into rdx–make-br–mov rdx,[123] ; Copy rdx to memory address 123 |
push src |
Insert a value onto the stack. Useful for passing arguments, saving registers, etc. |
push rbp |
pop dest |
Remove topmost value from the stack. Equivalent to “mov dest, [rsp]; add 8,rsp” |
pop rbp |
call func |
Push the address of the next instruction and start executing func. |
call print_int |
ret |
Pop the return program counter, and jump there. Ends a subroutine. |
ret |
add dest,src |
dest=dest+src |
add rax,rdx ; Add rbx to rax |
mul src |
Multiply rax and src as unsigned integers, and put the result in rax. High 64 bits of product (usually zero) go into rdx. |
mul rdx ; Multiply rax by rdx–make-br–; rax=low bits, rdx overflow |
div src |
Divide rax by src, and put the ratio into rax, and the remainder into rdx.–make-br–Bizarrely, on input rdx must be zero, or you get a SIGFPE. |
mov rdx,0 ; avoid error–make-br–div rcx ; compute rax/rcx |
shr val,bits |
Bitshift a value right by a constant, or the low 8 bits of rcx (“cl”).–make-br–Shift count MUST go in rcx, no other register will do! |
add rcx,4–make-br–shr rax,cl ; shift by rcx |
jmp label |
Goto the instruction label:. Skips anything else in the way. |
jmp post_mem–make-br–mov [0],rax ; Write to NULL!–make-br–post_mem: ; OK here… |
cmp a,b–make-br—-make-br– |
Compare two values. Sets flags that are used by the conditional jumps (below). |
cmp rax,10 |
jl label |
Goto label if previous comparison came out as less-than. Other conditionals available are: –make-br–jle (<=), je (==), jge (>=), jg (>), jne (!=), and many others.–make-br–Also available in unsigned comparisons: jb (<), jbe (<=), ja (>), jae (>=). |
jl loop_start ; Jump if rax<10 |
Constants, Registers, Memory¶
“12” means decimal 12; “0xF0” is hex. “some_function” is the address of the first instruction of the function. Memory access (use register as pointer): “[rax]”. Same as C “*rax”.–make-br–Memory access with offset (use register + offset as pointer): “[rax+4]”. Same as C “*(rax+4)”.–make-br–Memory access with scaled index (register + another register * scale): “[rax+rbx*4]”. Same as C “*(rax+rbx*4)”.
–make-br–See sandpile.org for an opcode map.
`O. Lawlor <http://lawlor.cs.uaf.edu/%7Eolawlor/>`__, `lawlor@alaska.edu <lawlor@alaska.edu>`__–make-br– Up to: `Class Site <../>`__, `CS <http://www.cs.uaf.edu/>`__, `UAF <http://www.uaf.edu/>`__