Here is a list of the available registers on the 386 and higher processors. This list shows the 32 bit registers. Most of the can be broken down to 16 or even 8 bits register.
General registers
EAX EBX ECX EDX
Segment registers
CS DS ES FS GS SS
Index and pointers
ESI EDI EBP EIP ESP
Indicator
EFLAGS
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.
32 bits : EAX EBX ECX EDX
16 bits : AX BX CX DX
8 bits : AH AL BH BL CH CL DH DL
The "H" and "L" suffix on the 8 bit registers stand for high byte and low byte. With this out of the way, let's see their individual main use
EAX,AX,AH,AL : Called the Accumulator register.
It is used for I/O port access, arithmetic, interrupt calls,
etc...
EBX,BX,BH,BL : Called the Base register
It is used as a base pointer for memory access
Gets some interrupt return values
ECX,CX,CH,CL : Called the Counter register
It is used as a loop counter and for shifts
Gets some interrupt values
EDX,DX,DH,DL : Called the Data register
It is used for I/O port access, arithmetic, some interrupt
calls.
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
CS : Holds the Code segment in which your program runs.
Changing its value might make the computer hang.
DS : Holds the Data segment that your program accesses.
Changing its value might give erronous data.
ES,FS,GS : These are extra segment registers available for
far pointer addressing like video memory and such.
SS : Holds the Stack segment your program uses.
Sometimes has the same value as DS.
Changing 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). The register with an "E" prefix can only be used in protected mode.
ES:EDI EDI DI : Destination index register
Used for string, memory array copying and setting and
for far pointer addressing with ES
DS:ESI EDI SI : Source index register
Used for string and memory array copying
SS:EBP EBP BP : Stack Base pointer register
Holds the base address of the stack
SS:ESP ESP SP : Stack pointer register
Holds the top address of the stack
CS:EIP EIP IP : Index Pointer
Holds the offset of the next instruction
It can only be read
The EFLAGS register
The EFLAGS register hold 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 :
Bit Label Desciption
---------------------------
0 CF Carry flag
2 PF Parity flag
4 AF Auxiliary carry flag
6 ZF Zero flag
7 SF Sign flag
8 TF Trap flag
9 IF Interrupt enable flag
10 DF Direction flag
11 OF Overflow flag
12-13 IOPL I/O Priviledge level
14 NT Nested task flag
16 RF Resume flag
17 VM Virtual 8086 mode flag
18 AC Alignment check flag (486+)
19 VIF Virutal interrupt flag
20 VIP Virtual interrupt pending flag
21 ID ID flag
Those that are not listed are reserved by Intel.
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. As far as I know, 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.
x86 Architecture
The Intel x86 processor uses complex instruction set computer (CISC) architecture, which means there is a modest number of special-purpose registers instead of large quantities of general-purpose registers. It also means that complicated special-purpose instructions will predominate.
The x86 processor traces its heritage at least as far back as the 8-bit Intel 8080 processor. Many peculiarities in the x86 instruction are due to the backward compatibility with that processor (and with its Zilog Z-80 variant).
Microsoft Win32 uses the x86 processor in 32-bit flat mode. This documentation will focus only on the flat mode.
Registers
The x86 architecture consists of the following unprivileged integer registers.
eax | Accumulator |
ebx | Base register |
ecx | Count register |
edx | Double-precision register |
esi | Source index register |
edi | Destination index register |
ebp | Base pointer register |
esp | Stack pointer |
All integer registers are 32 bit. However, many of them have 16-bit or 8-bit subregisters.
ax | Low 16 bits of eax |
bx | Low 16 bits of ebx |
cx | Low 16 bits of ecx |
dx | Low 16 bits of edx |
si | Low 16 bits of esi |
di | Low 16 bits of edi |
bp | Low 16 bits of ebp |
sp | Low 16 bits of esp |
al | Low 8 bits of eax |
ah | High 8 bits of ax |
bl | Low 8 bits of ebx |
bh | High 8 bits of bx |
cl | Low 8 bits of ecx |
ch | High 8 bits of cx |
dl | Low 8 bits of edx |
dh | High 8 bits of dx |
Operating on a subregister affects only the subregister and none of the parts outside the subregister. For example, storing to the ax register leaves the high 16 bits of theeax register unchanged.
When using the ? (Evaluate Expression) command, registers should be prefixed with an "at" sign ( @ ). For example, you should use ? @ax rather than ? ax. This ensures that the debugger recognizes ax as a register rather than a symbol.
However, the (@) is not required in the r (Registers) command. For instance, r ax=5 will always be interpreted correctly.
Two other registers are important for the processor's current state.
eip | instruction pointer |
flags | flags |
The instruction pointer is the address of the instruction being executed.
The flags register is a collection of single-bit flags. Many instructions alter the flags to describe the result of the instruction. These flags can then be tested by conditional jump instructions. See x86 Flags for details.
Calling Conventions
The x86 architecture has several different calling conventions. Fortunately, they all follow the same register preservation and function return rules:
-
Functions must preserve all registers, except for eax, ecx, and edx, which can be changed across a function call, and esp, which must be updated according to the calling convention.
-
The eax register receives function return values if the result is 32 bits or smaller. If the result is 64 bits, then the result is stored in the edx:eax pair.
The following is a list of calling conventions used on the x86 architecture:
-
Win32 (__stdcall)
Function parameters are passed on the stack, pushed right to left, and the callee cleans the stack.
-
Native C++ method call (also known as thiscall)
Function parameters are passed on the stack, pushed right to left, the "this" pointer is passed in the ecx register, and the callee cleans the stack.
-
COM (__stdcall for C++ method calls)
Function parameters are passed on the stack, pushed right to left, then the "this" pointer is pushed on the stack, and then the function is called. The callee cleans the stack.
-
__fastcall
The first two DWORD-or-smaller arguments are passed in the ecx and edx registers. The remaining parameters are passed on the stack, pushed right to left. The callee cleans the stack.
-
__cdecl
Function parameters are passed on the stack, pushed right to left, and the caller cleans the stack. The __cdecl calling convention is used for all functions with variable-length parameters.
Debugger Display of Registers and Flags
Here is a sample debugger register display:
eax=00000000 ebx=008b6f00 ecx=01010101 edx=ffffffff esi=00000000 edi=00465000 eip=77f9d022 esp=05cffc48 ebp=05cffc54 iopl=0 nv up ei ng nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000286
In user-mode debugging, you can ignore the iopl and the entire last line of the debugger display.
x86 Flags
In the preceding example, the two-letter codes at the end of the second line are flags. These are single-bit registers and have a variety of uses.
The following table lists the x86 flags:
Flag Code | Flag Name | Value | Flag Status | Status Description |
---|---|---|---|---|
of | Overflow Flag |
| nvov |
|
df | Direction Flag |
| updn |
|
if | Interrupt Flag |
| diei |
|
sf | Sign Flag |
| plng |
|
zf | Zero Flag |
| nzzr |
|
af | Auxiliary Carry Flag |
| naac |
|
pf | Parity Flag |
| pepo |
|
cf | Carry Flag |
| nccy |
|
tf | Trap Flag | If tf equals 1, the processor will raise a STATUS_SINGLE_STEP exception after the execution of one instruction. This flag is used by a debugger to implement single-step tracing. It should not be used by other applications. | ||
iopl | I/O Privilege Level | This is a two-bit integer, with values between zero and 3. It is used by the operating system to control access to hardware. It should not be used by applications. |
When registers are displayed as a result of some command in the Debugger Command window, it is the flag status that is displayed. However, if you want to change a flag using the r (Registers) command, you should refer to it by the flag code.
In the Registers window of WinDbg, the flag code is used to view or alter flags. The flag status is not supported.
Here is an example. In the preceding register display, the flag status ng appears. This means that the sign flag is currently set to 1. To change this, use the following command:
r sf=0
This sets the sign flag to zero. If you do another register display, the ng status code will not appear. Instead, the pl status code will be displayed.
The Sign Flag, Zero Flag, and Carry Flag are the most commonly-used flags.
Conditions
A condition describes the state of one or more flags. All conditional operations on the x86 are expressed in terms of conditions.
The assembler uses a one or two letter abbreviation to represent a condition. A condition can be represented by multiple abbreviations. For example, AE ("above or equal") is the same condition as NB ("not below"). The following table lists some common conditions and their meaning.
Condition Name | Flags | Meaning |
---|---|---|
Z | ZF=1 | Result of last operation was zero. |
NZ | ZF=0 | Result of last operation was not zero. |
C | CF=1 | Last operation required a carry or borrow. (For unsigned integers, this indicates overflow.) |
NC | CF=0 | Last operation did not require a carry or borrow. (For unsigned integers, this indicates overflow.) |
S | SF=1 | Result of last operation has its high bit set. |
NS | SF=0 | Result of last operation has its high bit clear. |
O | OF=1 | When treated as a signed integer operation, the last operation caused an overflow or underflow. |
NO | OF=0 | When treated as signed integer operation, the last operation did not cause an overflow or underflow. |
Conditions can also be used to compare two values. The cmp instruction compares its two operands, and then sets flags as if subtracted one operand from the other. The following conditions can be used to check the result of cmp value1, value2.
Condition Name | Flags | Meaning after a CMP operation. |
---|---|---|
E | ZF=1 | value1 == value2. |
NE | ZF=0 | value1 != value2. |
| SF=OF |
|
| ZF=1 or SF!=OF | value1 <= value2. Values are treated as signed integers. |
| ZF=0 and SF=OF | value1 > value2. Values are treated as signed integers. |
| SF!=OF | value1 < value2. Values are treated as signed integers. |
| CF=0 | value1 >= value2. Values are treated as unsigned integers. |
| CF=1 or ZF=1 | value1 <= value2. Values are treated as unsigned integers. |
| CF=0 and ZF=0 | value1 > value2. Values are treated as unsigned integers. |
| CF=1 | value1 < value2. Values are treated as unsigned integers. |
Conditions are typically used to act on the result of a cmp or test instruction. For example,
cmp eax, 5 jz equal
compares the eax register against the number 5 by computing the expression (eax - 5) and setting flags according to the result. If the result of the subtraction is zero, then the zr flag will be set, and the jz condition will be true so the jump will be taken.
Data Types
-
byte: 8 bits
-
word: 16 bits
-
dword: 32 bits
-
qword: 64 bits (includes floating-point doubles)
-
tword: 80 bits (includes floating-point extended doubles)
-
oword: 128 bits
Notation
The following table indicates the notation used to describe assembly language instructions.
Notation | Meaning |
---|---|
r, r1, r2... | Registers |
m | Memory address (see the succeeding Addressing Modes section for more information.) |
#n | Immediate constant |
r/m | Register or memory |
r/#n | Register or immediate constant |
r/m/#n | Register, memory, or immediate constant |
cc | A condition code listed in the preceding Conditions section. |
T | "B", "W", or "D" (byte, word or dword) |
accT | Size T accumulator: al if T = "B", ax if T = "W", or eax if T = "D" |
Addressing Modes
There are several different addressing modes, but they all take the form T ptr [expr], where T is some data type (see the preceding Data Types section) and expr is some expression involving constants and registers.
The notation for most modes can be deduced without much difficulty. For example, BYTE PTR [esi+edx*8+3] means "take the value of the esi register, add to it eight times the value of the edx register, add three, then access the byte at the resulting address."
Pipelining
The Pentium is dual-issue, which means that it can perform up to two actions in one clock tick. However, the rules on when it is capable of doing two actions at once (known as pairing) are very complicated.
Because x86 is a CISC processor, you do not have to worry about jump delay slots.
Synchronized Memory Access
Load, modify, and store instructions can receive a lock prefix, which modifies the instruction as follows:
-
Before issuing the instruction, the CPU will flush all pending memory operations to ensure coherency. All data prefetches are abandoned.
-
While issuing the instruction, the CPU will have exclusive access to the bus. This ensures the atomicity of the load/modify/store operation.
The xchg instruction automatically obeys the previous rules whenever it exchanges a value with memory.
All other instructions default to nonlocking.
Jump Prediction
Unconditional jumps are predicted to be taken.
Conditional jumps are predicted to be taken or not taken, depending on whether they were taken the last time they were executed. The cache for recording jump history is limited in size.
If the CPU does not have a record of whether the conditional jump was taken or not taken the last time it was executed, it predicts backward conditional jumps as taken and forward conditional jumps as not taken.
Alignment
The x86 processor will automatically correct unaligned memory access, at a performance penalty. No exception is raised.
A memory access is considered aligned if the address is an integer multiple of the object size. For example, all BYTE accesses are aligned (everything is an integer multiple of 1), WORD accesses to even addresses are aligned, and DWORD addresses must be a multiple of 4 in order to be aligned.
The lock prefix should not be used for unaligned memory accesses.
Send comments about this topic to Microsoft
Build date: 2/14/2012
http://msdn.microsoft.com/en-us/library/ff561502(v=vs.85).aspx