Skip to content

Registers

x86-64

x86-64 General-Purpose Registers

The 16 general-purpose registers (RAX–R15) with their byte, word, and dword sub-register aliases — and their conventional roles in the System V and Microsoft ABIs.

x86-64 has 16 general-purpose integer registers, each 64 bits wide. Sub-register aliases provide access to the lower 32, 16, and 8 bits.

Register map

64-bit32-bit16-bit8-bit high8-bit lowConventional use
raxeaxaxahalReturn value, accumulator
rbxebxbxbhblCallee-saved (SysV & MSVC)
rcxecxcxchcl4th arg (MSVC) / shift count
rdxedxdxdhdl3rd arg (MSVC) / 2nd return
rsiesisisil2nd arg (SysV) / string src
rdiedididil1st arg (SysV) / string dst
rbpebpbpbplFrame pointer (callee-saved)
rspespspsplStack pointer
r8r8dr8wr8b5th arg (SysV) / 3rd arg (MSVC)
r9r9dr9wr9b6th arg (SysV) / 4th arg (MSVC)
r10r10dr10wr10bTemp / syscall arg 4 (Linux)
r11r11dr11wr11bTemp / clobbered by SYSCALL
r12r12dr12wr12bCallee-saved
r13r13dr13wr13bCallee-saved
r14r14dr14wr14bCallee-saved
r15r15dr15wr15bCallee-saved (often GOT ptr in PIC)

"High" 8-bit aliases (ah, bh, ch, dh) exist only for the original four registers and cannot be used in instructions that also use a REX prefix.

Sub-register write behaviour

Write widthEffect on full 64-bit register
8-bit (al)Merges into rax — upper 56 bits unchanged
16-bit (ax)Merges into rax — upper 48 bits unchanged
32-bit (eax)Zero-extends into rax — upper 32 bits cleared
64-bit (rax)Full register replaced

The 32-bit zero-extension rule is a frequent source of confusion: writing eax implicitly clears the upper half of rax, so xor eax, eax suffices to zero the full rax.

Reverse-engineering notes

  • Seeing r15 used as a base pointer throughout a function often means the compiler spilled the Global Offset Table pointer there (PIC shared libraries on Linux).
  • rcx is clobbered by SYSCALL and by the Microsoft ABI's first argument — knowing the target ABI is essential before labelling rcx as loop counter vs. argument.
  • Decompilers infer variable types partly from which sub-register is used: al suggests char/uint8_t, ax suggests short/uint16_t, eax suggests int/uint32_t.