# x86_64
keywords: x86_64, x86, abi
- 64bit synonyms: `x86_64`, `x64`, `amd64`, `intel 64`
- 32bit synonyms: `x86`, `ia32`, `i386`
- ISA type: `CISC`
- Endianness: `little`
## Registers
### General purpose register
```markdown
bytes
[7:0] [3:0] [1:0] [1] [0] desc
----------------------------------------------------------
rax eax ax ah al accumulator
rbx ebx bx bh bl base register
rcx ecx cx ch cl counter
rdx edx dx dh dl data register
rsi esi si - sil source index
rdi edi di - dil destination index
rbp ebp bp - bpl base pointer
rsp esp sp - spl stack pointer
r8-15 rNd rNw - rNb
```
### Special register
```markdown
bytes
[7:0] [3:0] [1:0] desc
---------------------------------------------------
rflags eflags flags flags register
rip eip ip instruction pointer
```
### FLAGS register
```markdown
rflags
bits desc
-----------------------------
[11] OF overflow flag
[10] DF direction flag
[7] SF sign flag
[6] ZF zero flag
[4] AF auxiliary carry flag
[2] PF parity flag
[0] CF carry flag
```
## Addressing
```asm
movw [rax], rbx // save val in rbx at [rax]
movw [imm], rbx // save val in rbx at [imm]
movw rax, [rbx+4*rcx] // load val at [rbx+4*rcx] into rax
```
`rip` relative addressing:
```asm
lea rax, [rip+.my_str] // load addr of .my_str into rax
...
.my_str:
.asciz "Foo"
```
## Size directives
Explicitly specify size of the operation.
```x86asm
mov byte ptr [rax], 0xff // save 1 byte(s) at [rax]
mov word ptr [rax], 0xff // save 2 byte(s) at [rax]
mov dword ptr [rax], 0xff // save 4 byte(s) at [rax]
mov qword ptr [rax], 0xff // save 8 byte(s) at [rax]
```
## [SysV x86_64 ABI][sysvabi]
### Passing arguments to functions
- Integer/Pointer arguments
```markdown
reg arg
-----------
rdi 1
rsi 2
rdx 3
rcx 4
r8 5
r9 6
```
- Floating point arguments
```markdown
reg arg
-----------
xmm0 1
.. ..
xmm7 8
```
- Additional arguments are passed on the stack. Arguments are pushed
right-to-left (RTL), meaning next arguments are closer to current `rsp`.
### Return values from functions
- Integer/Pointer return values
```markdown
reg size
-----------------
rax 64 bit
rax+rdx 128 bit
```
- Floating point return values:
```markdown
reg size
-------------------
xmm0 64 bit
xmm0+xmm1 128 bit
```
### Caller saved registers
Caller must save these registers if they should be preserved across function
calls.
- `rax`
- `rcx`
- `rdx`
- `rsi`
- `rdi`
- `rsp`
- `r8` - `r11`
### Callee saved registers
Caller can expect these registers to be preserved across function calls. Callee
must must save these registers in case they are used.
- `rbx`
- `rbp`
- `r12` – `r15`
### Stack
- grows downwards
- frames aligned on 16 byte boundary
```text
Hi ADDR
| +------------+
| | prev frame |
| +------------+ <--- 16 byte aligned (X & ~0xf)
| [rbp+8] | saved RIP |
| [rbp] | saved RBP |
| [rbp-8] | func stack |
| | ... |
v +------------+
Lo ADDR
```
### Function prologue & epilogue
- prologue
```x86asm
push rbp // save caller base pointer
mov rbp, rsp // save caller stack pointer
```
- epilogue
```x86asm
mov rsp, rbp // restore caller stack pointer
pop rbp // restore caller base pointer
```
> Equivalent to `leave` instruction.
## ASM skeleton
Small assembler skeleton, ready to use with following properties:
- use raw Linux syscalls (`man 2 syscall` for ABI)
- no `C runtime (crt)`
- gnu assembler [`gas`][gas_doc]
- intel syntax
```x86asm
# file: greet.s
.intel_syntax noprefix
.section .text, "ax", @progbits
.global _start
_start:
mov rdi, 1 # fd
lea rsi, [rip + greeting] # buf
mov rdx, [rip + greeting_len] # count
mov rax, 1 # write(2) syscall nr
syscall
mov rdi, 0 # exit code
mov rax, 60 # exit(2) syscall nr
syscall
.section .rdonly, "a", @progbits
greeting:
.asciz "Hi ASM-World!\n"
greeting_len:
.int .-greeting
```
> Syscall numbers are defined in `/usr/include/asm/unistd.h`.
To compile and run:
```bash
> gcc -o greet greet.s -nostartfiles -nostdlib && ./greet
Hi ASM-World!
```
## References
- [SystemV AMD64 ABI][sysvabi]
- [AMD64 Vol1: Application Programming][amd64_vol1]
- [AMD64 Vol2: System Programming][amd64_vol2]
- [AMD64 Vol3: General-Purpose & System Instructions][amd64_vol3]
- [X86_64 Cheat-Sheet][x86_64_cheatsheet]
- [Intel 64 Vol1: Basic Architecture][intel64_vol1]
- [Intel 64 Vol2: Instruction Set Reference][intel64_vol2]
- [Intel 64 Vol3: System Programming Guide][intel64_vol3]
- [GNU Assembler][gas_doc]
- [GNU Assembler Directives][gas_directives]
- [GNU Assembler `x86_64` dependent features][gas_x86_64]
[sysvabi]: https://www.uclibc.org/docs/psABI-x86_64.pdf
[amd64_vol1]: https://www.amd.com/system/files/TechDocs/24592.pdf
[amd64_vol2]: https://www.amd.com/system/files/TechDocs/24593.pdf
[amd64_vol3]: https://www.amd.com/system/files/TechDocs/24594.pdf
[x86_64_cheatsheet]: https://cs.brown.edu/courses/cs033/docs/guides/x64_cheatsheet.pdf
[intel64_vol1]: https://software.intel.com/content/www/us/en/develop/download/intel-64-and-ia-32-architectures-software-developers-manual-volume-1-basic-architecture.html
[intel64_vol2]: https://software.intel.com/content/www/us/en/develop/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-2a-2b-2c-and-2d-instruction-set-reference-a-z.html
[intel64_vol3]: https://software.intel.com/content/www/us/en/develop/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-3a-3b-3c-and-3d-system-programming-guide.html
[gas_doc]: https://sourceware.org/binutils/docs/as
[gas_directives]: https://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops
[gas_x86_64]: https://sourceware.org/binutils/docs/as/i386_002dDependent.html