x86 & x64 Registers

The main tools to write programs in x86 assembly are the processor registers. The registers are like variables built in the processor. Using registers instead of memory to store values makes the process faster and cleaner. Note that the rules described here are more suggestions than strict rules. Some operations need absolutely some kind of registers but most of them you can use freely. This freedom however may be limited when if you are linking your code with another programming language since then the conventions of the compiler you are using may apply.

Note that this tutorial mainly deals with x86 registers, so some x64 registers will be mentioned partly only. Also, this page is meant to give a general overview on the important registers, so some registers might not be included. Some CPU families might even have added some extra registers not mentioned here.

Overview

Here is a list of the available registers on the i386 and higher processors. This list shows the 32 bit registers. Most of them can be broken down to 16 or even 8 bits register.

General registersSegment registersIndex and pointersIndicator
EAX EBX ECX EDXCS DS ES FS GS SSESI EDI EBP EIP ESPEFLAGS

General Registers

As the title says, general register are the one we use most of the time Most of the instructions perform on these registers. They all can be broken down into 16 and 8 bit registers. Note that the 64-bit parts can solely be accessed with 64-bit CPUs.

64-bit32-bit16-bit8-bit high8-bit low
RAXEAXAXAHAL
RBXEBXBXBHBL
RCXECXCXCHCL
RDXEDXDXDHDL

The "H" and "L" suffix on the 8 bit registers stand for high byte and low byte. The following picture taken from the NASM tutorial by Ray Toe may help understanding it better: Taken from the NASM Tutorial by Ray Toal

With this out of the way, let's see their individual main use

RegistersDesignationUsage
EAX,AX,AH,ALThe Accumulator registerIt is used for I/O port access, arithmetic, interrupt calls, etc...
EBX,BX,BH,BLThe Base registerIt is used as a base pointer for memory access. Gets some interrupt return values
ECX,CX,CH,CLThe Counter registerIt is used as a loop counter and for shifts. Gets some interrupt values
EDX,DX,DH,DLCalled the Data registerIt is used for I/O port access, arithmetic, some interrupt calls

NOTE: wiriting on Exx register will overwrite the higher 32-bit with 0 in x64 processors, but writing on the 16-bit or 8-bit parts will not overwrite anything else than that specific part itself.

The previous note can be explained by the following code:


mov eax, 0xFFFFFFFF     ; EAX = 0xFFFFFFFF (RAX = 0x00000000FFFFFFFF)
mov ax, 0x1111          ; EAX = 0xFFFF1111
mov al, 0xFF            ; EAX = 0xFFFF11FF

; alternative to above code:
mov eax, 0xFFFFFFFF     ; EAX = 0xFFFFFFFF
mov ah, 0x11            ; EAX = 0xFFFF11FF

Segment Registers

Segment registers hold the segment address of various items. They are only available in 16 values. They can only be set by a general register or special instructions. Some of them are critical for the good execution of the program and you might want to consider playing with them when you'll be ready for multi-segment programming

RegisterUsageWarning
CSHolds the Code segment in which your program runsChanging its value might make the computer hang
DSHolds the Data segment that your program accessesChanging its value might give erronous data
ES,FS,GSThese are extra segment registers available for far pointer addressing like video memory and such
SSHolds the Stack segment your program uses. Sometimes has the same value as DSChanging its value can give unpredictable results, mostly data related

Indexes and Pointers

Indexes and pointer and the offset part of and address. They have various uses but each register has a specific function. They some time used with a segment register to point to far address (in a 1Mb range).

RegisterDesignationUsageWarning
ES:EDI EDI DIDestination index registerUsed for string, memory array copying and setting and for far pointer addressing with ES
DS:ESI EDI SISource index registerUsed for string and memory array copying
SS:EBP EBP BPStack Base pointer registerHolds the base address of the stack
SS:ESP ESP SPStack pointer registerHolds the top address of the stack
CS:EIP EIP IPIndex PointerHolds the offset of the next instructionIt can only be read

NOTE: In x64, you may use RDI, RSI, RBP, RSP and RIP registers.

The EFLAGS Register

The EFLAGS register holds the state of the processor. It is modified by many intructions and is used for comparing some parameters, conditional loops and conditionnal jumps. Each bit holds the state of specific parameter of the last instruction. Here is a listing :

Note: in x64 Assembly, this register is called RFLAGS

BitLabelDesciptionUsageCategory
FLAGS
0CFCarry flagSet if the last arithmetic operation carried (addition) or borrowed (subtraction) a bit beyond the size of the register. This is then checked when the operation is followed with an add-with-carry or subtract-with-borrow to deal with values too large for just one register to containStatus
1ReservedAlways 1 in EFLAGS
2PFParity flagSet if the number of set bits in the least significant byte is a multiple of 2Status
3Reserved
4AFAuxiliary carry flagCarry of Binary Code Decimal (BCD) numbers arithmetic operationsStatus
5Reserved
6ZFZero flagSet if the result of an operation is Zero (0)Status
7SFSign flagSet if the result of an operation is negativeStatus
8TFTrap flagSet if step by step debuggingControl
9IFInterrupt enable flagSet if interrupts are enabledControl
10DFDirection flag (stream direction)If set, string operations will decrement their pointer rather than incrementing it, reading memory backwardsControl
11OFOverflow flagSet if signed arithmetic operations result in a value too large for the register to containStatus
12 - 13IOPLI/O Priviledge levelI/O Privilege Level of the current processSystem
14NTNested task flagControls chaining of interrupts. Set if the current process is linked to the next processSystem
15ReservedAlways 1 on 8086 and 186, always 0 on later models
EFLAGS
16RFResume flagResponse to debug exceptionsSystem
17VMVirtual 8086 mode flagSet if in 8086 compatibility modeSystem
18ACAlignment check flag (486+)Set if alignment checking of memory references is doneSystem
19VIFVirutal interrupt flagVirtual image of IFSystem
20VIPVirtual interrupt pending flagSet if an interrupt is pendingSystem
21IDID flagSupport for CPUID instruction if can be setSystem
22IDID flagSupport for CPUID instruction if can be setSystem
23 - 31VADVAD FlagSystem
RFLAGS
32 - 63Reserved

Floating Points

The x86_64 architecture comes with an x87 Floating Point Unit (FPU) which can make use of 8 registers and some floating point instructions. The registers are called from st0 to st7 and are each 80-bit long while they may preserve 32-bit or 64-bit values (float and double in C). FPU instructions generally will pop the first two items off the stack, act on them, and push the answer back on to the top of the stack.

FPU Instructions (in NASM)

The following table shows some basic instructions for the FPU. Note that this is not a full instruction list.

InstructionDesignationUseDescription
fldload floatfld qword [var]load value of var into st0
fststore floatfst qword [result]store value of st0 in result
faddadd floatfadd st1, st0st1 = st1 + st0
fsubsub floatfsub st1, st0st1 = st1 - st0
fmulmul floatsfmul qword [var], fmul st0, st1st0 = st0 var, st0 = st0 st1
fdivdiv floatsfdiv qword [var], fdiv sto, st1st0 = st0 / var, st0 = st0 / st1
fsqrtsqrtfsqrtsqrt of st0
fcoscosinusfcoscosinus of st0
fsinsinusfsinsinus of st0

NOTE: fcos and fsin are not part of the original x87 Instruction Set, but are rather an 80387 (i387) extension to the x87 instructions.

For more on this, read X86 Assembly/Floating Point.

Undocumented registers

There are registers on the 80386 and higher processors that are not well documented by Intel. These are divided in control registers, debug registers, test registers and protected mode segmentation registers. AFAIK, the control registers, along with the segmentation registers, are used in protected mode programming, all of these registers are available on 80386 and higher processors except the test registers that have been removed on the pentium. Control registers are CR0 to CR4, Debug registers are DR0 to DR7, test registers are TR3 to TR7 and the protected mode segmentation registers are GDTR (Global Descriptor Table Register), IDTR (Interrupt Descriptor Table Register), LDTR (Local DTR), and TR.

x64 registers

The x64 architecture came not only with a 64-bit extension of the existing 32-bit registers, but also with a newer set of registers. Those newer registers are as follwoing:

64-bit32-bit16-bit8-bit
r8r8dr8wr8b
r9r9dr9wr9b
r10r10dr10wr10b
r11r11dr11wr11b
r12r12dr12wr12b
r13r13dr13wr13b
r14r14dr14wr14b
r15r15dr15wr15b

x64 C/++ Calling Convention

  • The first four integer or pointer parameters are passed in the rcx, rdx, r8, and r9 registers.
  • The first four floating-point parameters are passed in the first four SSE registers, xmm0, xmm1, xmm2, xmm3.
  • The caller reserves space on the stack for arguments passed in registers. The called function can use this space to spill the contents of registers to the stack.
  • Any additional arguments are passed on the stack.
  • An integer or pointer return value is returned in the rax register, while a floating-point return value is returned in xmm0.
  • rax, rcx, rdx, r8-r11 are volatile.
  • rbx, rbp, rdi, rsi, r12-r15 are nonvolatile.

NOTE: The xmm0 to xmm7 registers are 128-bit wide each and are part of the Streaming SIMD Extension (SSE).

Blog Comments powered by Disqus.