Concepts
x86-64x86-64 Addressing Modes
x86-64 memory operands follow the base + index*scale + displacement formula, encoded in the ModRM and SIB bytes — understanding them is essential for reading any memory access.
x86-64 memory operands use a general formula:
[base + index*scale + displacement]
All four components are optional; any combination is valid (subject to encoding constraints).
Components
| Component | Description | Values |
|---|---|---|
base | Any 64-bit GPR (or RIP for RIP-relative) | rax–r15, rip |
index | Any GPR except RSP | rax–r15 (not rsp) |
scale | Multiplier for index | 1, 2, 4, 8 |
displacement | Signed constant offset | 8-bit or 32-bit |
Examples
mov rax, [rbx] ; base only
mov rax, [rbx + 8] ; base + disp8
mov rax, [rbx + 0x100] ; base + disp32
mov rax, [rbx + rcx] ; base + index (scale=1)
mov rax, [rbx + rcx*4] ; base + index*scale
mov rax, [rbx + rcx*8 + 0x10] ; full form
mov rax, [rip + 0x1234] ; RIP-relative (PIC globals, x86-64 only)
mov rax, [rcx*4 + label] ; index*scale + disp (no base — uses disp32)Array and struct access patterns
int arr[100];
arr[i] → mov eax, [arr_base + rdi*4] ; int = 4 bytes
struct Foo { int x; int y; long z; };
foo->z → mov rax, [rdi + 8] ; offset of z = 8RIP-relative addressing
[rip + disp32] is the standard way to reference globals and string literals
in position-independent code on x86-64. The displacement is relative to the
address of the next instruction (i.e. RIP after fetch).
lea rdi, [rip + 0x234] ; load address of string 0x234 bytes ahead
call printfReverse-engineering notes
[rax + rbx*8]almost always means array indexing:raxis the base pointer,rbxis the index, and8issizeof(element).[rdi + 0x10]accessing a struct field:0x10is the byte offset. Match against the struct definition to identify the field.- Disassemblers display
[rip + X]as the resolved target address — check whether it lands in.rodata(string/constant) or.data/.bss(variable). - When
RSPis the base, you are looking at a local variable or argument access (frame-pointer-omitted code).