Encoding Real x86 Instructions

 Source: CIS-77 Home http://www.c-jump.com/CIS77/CIS77syllabus.htm

Encoding x86 Instructions

  • It is time to take a look that the actual machine instruction format of the x86 CPU family.
  • They don't call the x86 CPU a Complex Instruction Set Computer (CISC) for nothing!
  • Although more complex instruction encodings exist, no one is going to challenge that the x86 has a complex instruction encoding!

1. x86 Instructions Overview

x86 Instruction Encoding:

x86 Instruction Encoding

Although the diagram seems to imply that instructions can be up to 16 bytes long, in actuality the x86 will not allow instructions greater than 15 bytes in length.

The prefix bytes are not the opcode expansion prefix discussed earlier - they are special bytes to modify the behavior of existing instructions.

2. x86 Instruction Format Reference

Another view of the x86 instruction format:

The x86 instruction format

Additional reference:
  • Intel x86 instructions by opcode
  • Intel x86 instructions by mnemonic
  • Brief Intel x86 instruction reference.

3. x86 Opcode Sizes

The x86 CPU supports two basic opcode sizes:
  1. standard one-byte opcode
  2. two-byte opcode consisting of a 0Fh opcode expansion prefix byte.
    The second byte then specifies the actual instruction.
  • The x86 opcode bytes are 8-bit equivalents of iii field that we discussed in simplified encoding.
  • This provides for up to 512 different instruction classes, although the x86 does not yet use them all.

3.1. x86 ADD Instruction Opcode

x86 ADD instruction opcode:

x86 ADD Opcode

Bit number one, marked d, specifies the direction of the data transfer:

  • If d = 0 then the destination operand is a memory location, e.g.

            add [ebx], al
  • If d = 1 then the destination operand is a register, e.g.

            add al, [ebx]
Bit number zero marked s specifies the size of the operands the ADD instruction operates upon:
  • If s = 0 then the operands are 8-bit registers and memory locations.
  • If s = 1 then the operands are either 16-bits or 32-bits:
    • Under 32-bit operating systems the default is 32-bit operands if s = 1.
    • To specify a 16-bit operand (under Windows or Linux) you must insert a special operand-size prefix byte in front of the instruction (example of this later.)
You'll soon see that this direction bit d creates a problem that results in one instruction have two different possible opcodes.

4. Encoding x86 Instruction Operands, MOD-REG-R/M Byte

The MOD-REG-R/M byte specifies instruction operands and their addressing mode(*):

The MOD field specifies x86 addressing mode:

MOD | Meaning
00 | Register indirect addressing mode or SIB with no displacement (when R/M = 100) or Displacement only addressing mode (when R/M = 101).
01 | One-byte signed displacement follows addressing mode byte(s).
10 | Four-byte signed displacement follows addressing mode byte(s).
11 | Register addressing mode.

The REG field specifies source or destination register:

REG Value | Register if data size is eight bits | Register if data size is 16-bits | Register if data size is 32 bits
000 | al | ax | eax
001 | cl | cx | ecx
010 | dl | dx | edx
011 | bl | bx | ebx
100 | ah | sp | esp
101 | ch | bp | ebp
110 | dh | si | esi
111 | bh | di | edi

The R/M field, combined with MOD, specifies either

  1. the second operand in a two-operand instruction, or
  2. the only operand in a single-operand instruction like NOT or NEG.
The d bit in the opcode determines which operand is the source, and which is the destination:
  • d=0: MOD R/M <- REG, REG is the source
  • d=1: REG <- MOD R/M, REG is the destination
(*) Technically, registers do not have an address, but we apply the term addressing mode to registers nonetheless.

5. General-Purpose Registers

16-bit general-purpose registers

Since the processor accesses registers more quickly than it accesses memory, you can make your programs run faster by keeping the most-frequently used data in registers.

  • The EAX, EDX, ECX, EBX, EBP, EDI, and ESI registers are 32-bit general-purpose registers, used for temporary data storage and memory access.
  • The AX, DX, CX, BX, BP, DI, and SI registers are 16-bit equivalents of the above, they represent the low-order 16 bits of 32-bit registers.
  • The AH, DH, CH, and BH registers represent the high-order 8 bits of the corresponding registers.
  • Similarly, AL, DL, CL, and BL represent the low-order 8 bits of the registers.

6. REG Field of the MOD-REG-R/M Byte

See MOD-REG-R/M Byte.

Depending on the instruction, this can be either the source or the destination operand.

Many instructions have the d (direction) field in their opcode to choose REG operand role:

  1. If d=0, REG is the source,
    MOD R/M <- REG.
  2. If d=1, REG is the destination,
    REG <- MOD R/M.
(*) For certain (often single-operand or immediate-operand) instructions, the REG field may contain an opcode extension rather than the register bits. The R/M field will specify the operand in such case.

9. MOD R/M Byte and Addressing Modes

MOD R/M Addressing Mode
=== === ================================
 00 000 [ eax ]
 01 000 [ eax + disp8 ]               (1)
 10 000 [ eax + disp32 ]
 11 000 register  ( al / ax / eax )   (2)
 00 001 [ ecx ]
 01 001 [ ecx + disp8 ]
 10 001 [ ecx + disp32 ]
 11 001 register  ( cl / cx / ecx )
 00 010 [ edx ]
 01 010 [ edx + disp8 ]
 10 010 [ edx + disp32 ]
 11 010 register  ( dl / dx / edx )
 00 011 [ ebx ]
 01 011 [ ebx + disp8 ]
 10 011 [ ebx + disp32 ]
 11 011 register  ( bl / bx / ebx )
 00 100 SIB  Mode                     (3)
 01 100 SIB  +  disp8  Mode
 10 100 SIB  +  disp32  Mode
 11 100 register  ( ah / sp / esp )
 00 101 32-bit Displacement-Only Mode (4)
 01 101 [ ebp + disp8 ]
 10 101 [ ebp + disp32 ]
 11 101 register  ( ch / bp / ebp )
 00 110 [ esi ]
 01 110 [ esi + disp8 ]
 10 110 [ esi + disp32 ]
 11 110 register  ( dh / si / esi )
 00 111 [ edi ]
 01 111 [ edi + disp8 ]
 10 111 [ edi + disp32 ]
 11 111 register  ( bh / di / edi )
  1. Addressing modes with 8-bit displacement fall in the range -128..+127 and require only a single byte displacement after the opcode (Faster!)
  2. The size bit in the opcode specifies 8 or 32-bit register size. To select a 16-bit register requires a prefix byte.
  3. The so-called scaled indexed addressing modes, SIB = scaled index byte mode.
  4. Note that there is no [ ebp ] addressing. It's slot is occupied by the 32-bit displacement only addressing mode. Intel decided that programmers can use [ ebp+ disp8 ] addressing mode instead, with its 8-bit displacement set equal to zero (instruction is a little longer, though.)

8. SIB (Scaled Index Byte) Layout

Scaled index byte layout:

SIB, Scaled index byte layout

Scale Value | Index*Scale Value
00 | Index*1
01 | Index*2
10 | Index*4
11 | Index*8
Index | Register
000 | EAX
001 | ECX
010 | EDX
011 | EBX
100 | Illegal
101 | EBP
110 | ESI
111 | EDI
Base | MOD | Register
000 | xx | EAX
001 | xx | ECX
010 | xx | EDX
011 | xx | EBX
100 | xx | ESP
101 | 00 | Displacement-only
 | 01, 10 | EBP
110 | xx | ESI
111 | xx | EDI
  • Scaled indexed addressing mode uses the second byte (namely, SIB byte) that follows the MOD-REG-R/M byte in the instruction format.
  • The MOD field still specifies the displacement size of zero, one, or four bytes.
    • The MOD-REG-R/M and SIB bytes are complex, because Intel reused 16-bit addressing circuitry in the 32-bit mode, rather than simply abandoning the 16-bit format in the 32-bit mode.
    • There are good hardware reasons for this, but the end result is a complex scheme for specifying addressing modes in the opcodes.

8.1. Scaled Indexed Addressing Mode

[ reg32 + eax*n ] MOD = 00
[ reg32 + ebx*n ]
[ reg32 + ecx*n ]
[ reg32 + edx*n ]
[ reg32 + ebp*n ]
[ reg32 + esi*n ]
[ reg32 + edi*n ]

[ disp + reg8 + eax*n ] MOD = 01
[ disp + reg8 + ebx*n ]
[ disp + reg8 + ecx*n ]
[ disp + reg8 + edx*n ]
[ disp + reg8 + ebp*n ]
[ disp + reg8 + esi*n ]
[ disp + reg8 + edi*n ]

[ disp + reg32 + eax*n ] MOD = 10
[ disp + reg32 + ebx*n ]
[ disp + reg32 + ecx*n ]
[ disp + reg32 + edx*n ]
[ disp + reg32 + ebp*n ]
[ disp + reg32 + esi*n ]
[ disp + reg32 + edi*n ]

[ disp + eax*n ] MOD = 00, and
[ disp + ebx*n ] BASE field = 101
[ disp + ecx*n ]
[ disp + edx*n ]
[ disp + ebp*n ]
[ disp + esi*n ]
[ disp + edi*n ]
Note: n = 1, 2, 4, or 8.

In each scaled indexed addressing mode the MOD field in MOD-REG-R/M byte specifies the size of the displacement. It can be zero, one, or four bytes:

    MOD R/M  Addressing Mode
    --- ---  ---------------------------
     00 100  SIB
     01 100  SIB + disp8
     10 100  SIB + disp32
The Base and Index fields of the SIB byte select the base and index registers, respectively.

Note that this addressing mode does not allow the use of the ESP register as an index register. Presumably, Intel left this particular mode undefined to provide the ability to extend the addressing modes in a future version of the CPU.

9. Examples

9.1. Encoding ADD Instruction Example

  • The ADD opcode can be decimal 0, 1, 2, or 3, depending on the direction and size bits in the opcode:

  • How could we encode various forms of the ADD instruction using different addressing modes?

9.2 Encoding ADD CL, AL Instruction

  • Encoding ADD AL, CL Instruction

  • Interesting side effect of the direction bit and the MOD-REG-R/M byte organization: some instructions can have two different opcodes, and both are legal!

  • For example, encoding of

        add cl, al

    could be 00 C1 (if d=0), or 02 C8, if d bit is set to 1.

  • The possibility of opcode duality issue here applies to all instructions with two register operands.

9.3. Encoding ADD ECX, EAX Instruction

  •     add ecx, eax

  • Encoding ADD ECX, EAX Instruction

  • Note that we could also encode ADD ECX, EAX using the bytes 03 C8.

9.4. Encoding ADD EDX, DISPLACEMENT Instruction

  • Encoding the ADD EDX, DISP Instruction:

        add edx, disp
      Encoding the ADD EDX, DISP Instruction

9.5. Encoding ADD EDI, [EBX] Instruction

  • Encoding the ADD EDI, [ EBX ] instruction:

        add edi, [ebx]
      Encoding the ADD EDI, [EBX] Instruction

9.6. Encoding ADD EAX, [ ESI + disp8 ] Instruction

  • Encoding the ADD EAX, [ ESI + disp8 ] instruction:

        add eax, [ esi + disp8 ]
      Encoding the ADD EAX, [ ESI + disp8 ] Instruction

9.7. Encoding ADD EBX, [ EBP + disp32 ] Instruction

  • Encoding the ADD EBX, [ EBP + disp32 ] instruction:

        add ebx, [ ebp + disp32 ]
      Encoding the ADD EBX, [ EBP + disp32 ] Instruction

9.8. Encoding ADD EBP, [ disp32 + EAX*1 ] Instruction

  • Encoding the ADD EBP, [ disp32 + EAX*1 ] Instruction

        add ebp, [ disp32 + eax*1 ]
      Encoding the ADD EBP, [ disp32 + EAX*1 ] Instruction

9.9. Encoding ADD ECX, [ EBX + EDI*4 ] Instruction

  • Encoding the ADD ECX, [ EBX + EDI*4 ] Instruction

        add ecx, [ ebx + edi*4 ]
      Encoding ADD ECX, [ EBX + EDI*4 ] Instruction

10. Encoding ADD Immediate Instruction

Encoding x86 immediate operands:

Encoding Immediate Operands

MOD-REG-R/M and SIB bytes have no bit combinations to specify an immediate operand.

Instead, x86 uses a entirely different instruction format to specify instruction with an immediate operand.

There are three rules that apply:

  1. If opcode high-order bit set to 1, then instruction has an immediate constant.
  2. There is no direction bit in the opcode:
    • : indeed, you cannot specify a constant as a destination operand!
    • Therefore, destination operand is always the location encoded in the MOD-R/M bits of the the MOD-REG-R/M byte.
    • In place of the direction bit d, the opcode has a sign extension x bit instead:
      • For 8-bit operands, the CPU ignores x bit.
      • For 16-bit and 32-bit operands, x bit specifies the size of the Constant following at the end of the instruction:
        • If x bit contains zero, the Constant is the same size as the operand (i.e., 16 or 32 bits).
        • If x bit contains one, the Constant is a signed 8-bit value, and the CPU sign-extends this value to the appropriate size before adding it to the operand.
      • This little x trick often makes programs shorter, because adding small-value constants to 16 or 32 bit operands is very common.
  3. The third difference between the ADD-immediate and the standard ADD instruction is the meaning of the REG field in the MOD-REG-R/M byte:
    • Since the instruction implies that
      • the source operand is a constant, and
      • MOD-R/M fields specify the destination operand,
      the instruction does not need to use the REG field to specify an operand.
    • Instead, the x86 CPU uses these three bits as an opcode extension.
    • For the ADD-immediate instruction the REG bits must contain zero.
    • Other bit patterns would correspond to a different instruction.
Note that when adding a constant to a memory location, the displacement (if any) immediately precedes the immediate (constant) value in the opcode sequence.

11. Encoding Eight, Sixteen, and Thirty-Two Bit Operands

x86 ADD Opcode:

x86 ADD Opcode

  • When Intel designed the 8086, one bit in the opcode, s, selected between 8 and 16 bit integer operand sizes.
  • Later, when CPU added 32-bit integers to its architecture on 80386 chip, there was a problem:
    • three encodings were needed to support 8, 16, and 32 bit sizes.
  • Solution was an operand size prefix byte.
  • Intel studied x86 instruction set and came to the conclusion:
    • in a 32-bit environment, programs were more likely to use 8-bit and 32-bit operands far more often than 16-bit operands.
  • So Intel decided to let the size bit s in the opcode select between 8- and 32-bit operands.

11.1. Encoding Sixteen Bit Operands

x86 instruction format:

32-bit programs don't use 16-bit operands that often, but they do need them now and then.

To allow for 16-bit operands, Intel added prefix a 32-bit mode instruction with the operand size prefix byte with value 66h.

This prefix byte tells the CPU to operand on 16-bit data rather than 32-bit data.

  • There is nothing programmer has to do explicitly to put an operand size prefix byte in front of a 16-bit instruction:
    • the assembler does this automatically as soon as 16-bit operand is found in the instruction.
  • However, keep in mind that whenever you use a 16-bit operand in a 32-bit program, the instruction is longer by one byte:
        Opcode     Instruction
    --------   ------------
    41h        INC ECX
    66h 41h    INC CX
  • Be careful about using 16-bit instructions if size (and to a lesser extent, speed) are important, because
    1. instructions are longer, and
    2. slower because of their effect on the instruction cache.

12. x86 Instruction Prefix Bytes

  • x86 instruction can have up to 4 prefixes.
  • Each prefix adjusts interpretation of the opcode:
    1. Repeat/lock prefix byte guarantees that instruction will have exclusive use of all shared memory, until the instruction completes execution:
              F0h = LOCK
    2. String manipulation instruction prefixes
              F3h = REP, REPE
        F2h = REPNE
      where
      • REP repeats instruction the number of times specified by iteration count ECX.
      • REPE and REPNE prefixes allow to terminate loop on the value of ZF CPU flag.
      Related string manipulation instructions are:
      • MOVS, move string
      • STOS, store string
      • SCAS, scan string
      • CMPS, compare string, etc.
      See also string manipulation sample program: rep_movsb.asm
    3. Segment override prefix causes memory access to use specified segment instead of default segment designated for instruction operand.
              2Eh = CS
        36h = SS
        3Eh = DS
        26h = ES
        64h = FS
        65h = GS
    4. Operand override, 66h. Changes size of data expected by default mode of the instruction e.g. 16-bit to 32-bit and vice versa.
    5. Address override, 67h. Changes size of address expected by the instruction. 32-bit address could switch to 16-bit and vice versa.

13. Alternate Encodings for Instructions

  • To shorten program code, Intel created alternate (shorter) encodings of some very commonly used instructions.
  • For example, x86 provides a single byte opcode for
        add al, constant    ; one-byte opcode and no MOD-REG-R/M byte
    add eax, constant   ; one-byte opcode and no MOD-REG-R/M byte
    the opcodes are 04h and 05h, respectively. Also,
  • These instructions are one byte shorter than their standard ADD immediate counterparts.
  • Note that
        add ax, constant   ; operand size prefix byte + one-byte opcode, no MOD-REG-R/M byte
    requires an operand size prefix just as a standard ADD AX, constant instruction, yet is still one byte shorter than the corresponding standard version of ADD immediate.
  • Any decent assembler will automatically choose the shortest possible instruction when translating program into machine code.
  • Intel only provides alternate encodings only for the accumulator registers AL, AX, EAX.
  • This is a good reason to use accumulator registers if you have a choice
    (also a good reason to take some time and study encodings of the x86 instructions.)

14. x86 Opcode Summary

  • x86 opcodes are represented by one or two bytes.
  • Opcode could extend into unused bits of MOD-REG-R/M byte.
  • Opcode encodes information about
    • operation type,
    • operands,
    • size of each operand, including the size of an immediate operand.

14.1. MOD-REG-R/M Byte Summary

MOD-REG-R/M Byte:

  • MOD-REG-R/M byte follows one or two opcode bytes of the instruction
  • It provides addressing mode information for one or two operands.
  • If operand is in memory, or operand is a register:
    • MOD field (bits [7:6]), combined with the R/M field (bits [2:0]), specify memory/register operand, as well as its addressing mode.
    • REG field (bits [5:3]) specifies another register operand in of the two-operand instruction.

15. ISA Design Considerations

  • Instruction set architecture design that can stand the test of time is a true intellectual challenge.
  • It takes several compromises between space and efficiency to assign opcodes and encode instruction formats.
  • Today people are using Intel x86 instruction set for purposes never intended by original designers.
  • Extending the CPU is a very difficult task.
  • The instruction set can become extremely complex.
  • If x86 CPU was designed from scratch today, it would have a totally different ISA!
  • Software developers usually don't have a problem adapting to a new architecture when writing new software...
    ...but they are very resistant to moving existing software from one platform to another.
  • This is the primary reason the Intel x86 platform remains so popular to this day.

15.1. ISA Design Challenges

  • Allowing for future expansion of the chip requires some undefined opcodes.
  • From the beginning there should be a balance between the number of undefined opcodes and
    1. the number of initial instructions, and
    2. the size of your opcodes (including special assignments.)
  • Hard decisions:
    • Reduce the number of instructions in the initial instruction set?
    • Increase the size of the opcode?
    • Rely on an opcode prefix byte(s), which makes later added instructions longer?
  • There are no easy answers to these challenges for CPU designers!

16. Intel Architecture Software Developer's Manual

Classic Intel Pentium II Architecture Software Developer's Manual contains three parts:
  1. Volume 1 , Intel Basic Architecture: Order Number 243190 , PDF, 2.6 MB.
  2. Volume 2 , Instruction Set Reference: Order Number 243191 , PDF, 6.6 MB.
  3. Volume 3 , System Programing Guide: Order Number 243192 , PDF, 5.1 MB.
It is highly recommended that you download the above manuals and use them as a reference.

16.1. Intel Instruction Set Reference (Volume2)

  • Chapter 3 of the Instruction Set Reference describes
    • each Intel instruction in detail
    • algorithmic description of each operation
    • effect on flags
    • operand(s), their sizes and attributes
    • CPU exceptions that may be generated.
  • The instructions are arranged in alphabetical order.
  • Appendix A provides opcode map for the entire Intel Architecture instruction set.

16.2. Chapter 3 of Intel Instruction Set Reference

  • Chapter 3 begins with instruction format example and explains the Opcode column encoding.
  • The Opcode column gives the complete machine codes as it is understood by the CPU.
  • When possible, the actual machine code bytes are given as exact hexadecimal bytes, in the same order in which they appear in memory.
  • However, there are opcode definitions other than hexadecimal bytes...

16.3. Intel Reference Opcode Bytes

  • Fow example,

    INC instruction reference page

16.4. Intel Reference Opcode Bytes, Cont.

  • /digit - A digit between 0 and 7 indicates that
    • The reg field of Mod R/M byte contains the instruction opcode extension.
    • The r/m (register or memory) operand of Mod R/M byte indicates
          R/M Addressing Mode
    === ===========================
    000 register ( al / ax / eax )
    001 register ( cl / cx / ecx )
    010 register ( dl / dx / edx )
    011 register ( bl / bx / ebx )
    100 register ( ah / sp / esp )
    101 register ( ch / bp / ebp )
    110 register ( dh / si / esi )
    111 register ( bh / di / edi )
  • The size bit in the opcode specifies 8 or 32-bit register size.
  • A 16-bit register requires a prefix byte:

        Opcode     Instruction
    --------   ------------
    41h        INC ECX
    66h 41h    INC CX

16.5. Intel Reference Opcode Bytes, Cont.

  • /r - Indicates that the instruction uses the Mod R/M byte of the instruction.
  • Mod R/M byte contains both
    • a register operand reg and
    • an r/m (register or memory) operand.

16.6. Intel Reference Opcode Bytes, Cont.

  • cb, cw, cd, cp - A 1-byte (cb), 2-byte (cw), 4-byte (cd), or 6-byte (cp) value,
    following the opcode, is used to specify
    • a code offset,
    • and possibly a new value for the code segment register CS.

16.7. Intel Reference Opcode Bytes, Cont.

  • ib, iw, id - A 1-byte (ib), 2-byte (iw), or 4-byte (id) indicates presence of the immediate operand in the instruction.
  • Typical order of opcode bytes is
    • opcode
    • Mod R/M byte (optional)
    • SIB scale-indexing byte (optional)
    • immediate operand.
  • The opcode determines if the operand is a signed value.
  • All words and doublewords are given with the low-order byte first (little endian).

16.8. Intel Reference Opcode Bytes, Cont.

  • +rb, +rw, +rd - A register code, from 0 through 7, added to the hexadecimal byte given at the left of the plus sign to form a single opcode byte.
  • Register Encodings Associated with the +rb, +rw, and +rd:

    Register Encodings Associated with the +rb, +rw, and +rd

    For example,

    INC instruction reference page

16.9. Intel Reference Instruction Column

  • The Instruction column gives the syntax of the instruction statement as it would appear in a 386 Assembly program.
  • For example,

    INC instruction reference page


X86-64 Instruction Encoding - OSDev Wiki

X86-64 Instruction Encoding

From OSDev Wiki
Jump to: navigation, search

This article describes how x86 and x86-64 instructions are encoded.

General Overview

An x86-64 instruction may be at most 15 bytes in length. It consists of the following components in the given order, where the prefixes are at the least-significant (lowest) address in memory:

  • Legacy prefixes (1-4 bytes, optional)
  • Opcode with prefixes (1-4 bytes, required)
  • ModR/M (1 byte, if required)
  • SIB (1 byte, if required)
  • Displacement (1, 2, 4 or 8 bytes, if required)
  • Immediate (1, 2, 4 or 8 bytes, if required)

Registers

The registers are encoded using the 4-bit values in the X.Reg column of the following table.

X.Reg | 8-bit GP | 16-bit GP | 32-bit GP | 64-bit GP | 80-bit x87 | 64-bit MMX | 128-bit XMM | 256-bit YMM | 16-bit Segment | 32-bit Control | 32-bit Debug
b0.000 (0) | AL | AX | EAX | RAX | ST0 | MMX0 | XMM0 | YMM0 | ES | CR0 | DR0
b0.001 (1) | CL | CX | ECX | RCX | ST1 | MMX1 | XMM1 | YMM1 | CS | CR1 | DR1
b0.010 (2) | DL | DX | EDX | RDX | ST2 | MMX2 | XMM2 | YMM2 | SS | CR2 | DR2
b0.011 (3) | BL | BX | EBX | RBX | ST3 | MMX3 | XMM3 | YMM3 | DS | CR3 | DR3
b0.100 (4) | AH, SPL1 | SP | ESP | RSP | ST4 | MMX4 | XMM4 | YMM4 | FS | CR4 | DR4
b0.101 (5) | CH, BPL1 | BP | EBP | RBP | ST5 | MMX5 | XMM5 | YMM5 | GS | CR5 | DR5
b0.110 (6) | DH, SIL1 | SI | ESI | RSI | ST6 | MMX6 | XMM6 | YMM6 | - | CR6 | DR6
b0.111 (7) | BH, DIL1 | DI | EDI | RDI | ST7 | MMX7 | XMM7 | YMM7 | - | CR7 | DR7
b1.000 (8) | R8L | R8W | R8D | R8 | - | MMX0 | XMM8 | YMM8 | ES | CR8 | DR8
b1.001 (9) | R9L | R9W | R9D | R9 | - | MMX1 | XMM9 | YMM9 | CS | CR9 | DR9
b1.010 (10) | R10L | R10W | R10D | R10 | - | MMX2 | XMM10 | YMM10 | SS | CR10 | DR10
b1.011 (11) | R11L | R11W | R11D | R11 | - | MMX3 | XMM11 | YMM11 | DS | CR11 | DR11
b1.100 (12) | R12L | R12W | R12D | R12 | - | MMX4 | XMM12 | YMM12 | FS | CR12 | DR12
b1.101 (13) | R13L | R13W | R13D | R13 | - | MMX5 | XMM13 | YMM13 | GS | CR13 | DR13
b1.110 (14) | R14L | R14W | R14D | R14 | - | MMX6 | XMM14 | YMM14 | - | CR14 | DR14
b1.111 (15) | R15L | R15W | R15D | R15 | - | MMX7 | XMM15 | YMM15 | - | CR15 | DR15

1: When any REX prefix is used, SPL, BPL, SIL and DIL are used. Otherwise, without any REX prefix AH, CH, DH and BH are used.

Legacy Prefixes

Each instruction can have up to four prefixes. Sometimes a prefix is required for the instruction while it loses it's original meaning (i.e. a 'mandatory prefix'). The following prefixes can be used, the order does not matter:

  • Prefix group 1
    • 0xF0: LOCK prefix
    • 0xF2: REPNE/REPNZ prefix
    • 0xF3: REP or REPE/REPZ prefix
  • Prefix group 2
    • 0x2E: CS segment override
    • 0x36: SS segment override
    • 0x3E: DS segment override
    • 0x26: ES segment override
    • 0x64: FS segment override
    • 0x65: GS segment override
    • 0x2E: Branch not taken
    • 0x3E: Branch taken
  • Prefix group 3
    • 0x66: Operand-size override prefix
  • Prefix group 4
    • 0x67: Address-size override prefix

When there are two or more prefixes from a single group, the behavior is undefined. Some processors ignore the subsequent prefixes from the same group, or use only the last prefix specified for any group.

LOCK prefix

With the LOCK prefix, certain read-modify-write instructions are executed atomically. The LOCK prefix can only be used with the following instructions or an Invalid Opcode Exception occurs: ADC, ADD, AND, BTC, BTR, BTS, CMPXCHG, CMPXCHG8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XADD, XCHG and XOR.

REPNE/REPNZ, REP and REPE/REPZ prefixes

The repeat prefixes cause string handling instructions to be repeated.

The REP prefix will repeat the associated instruction up to CX times, decreasing CX with every repetition. It can be used with the INS, LODS, MOVS, OUTS and STOS instructions.

REPE and REPZ are synonyms and repeat the instruction until CX reaches 0 or when ZF is set to 0. It can be used with the CMPS, CMPSB, CMPSD, CMPSW, SCAS, SCASB, SCASD and SCASW instructions.

REPNE and REPNZ also are synonyms and repeat the instruction until CX reaches 0 or when ZF is set to 1. It can be used with the CMPS, CMPSB, CMPSD, CMPSW, SCAS, SCASB, SCASD and SCASW instructions

CS, SS, DS, ES, FS and GS segment override prefixes

Segment overrides are used with instructions that reference non-stack memory. The default segment is implied by the instruction, and using a specific override forces the use of the specified segment for memory operands.

In 64-bit the CS, SS, DS and ES segment overrides are ignored.

Branch taken/not taken prefixes

Branch hints may be used to lessen the impact of branch misprediction somewhat. The 'branch taken' hint is a strong hint, while the 'branch not taken' hint is a weak hint. The branch hints are only supported by Intel since the Pentium 4. Whether using them on AMD architectures has any (positive or negative) effect at all is not known.

Operand-size and address-size override prefix

The default operand-size and address-size can be overridden using these prefix. See the following table:

Operating mode | CS.d | 0x66 operand prefix | 0x67 address prefix | REX.W | Operand-size | Address-size
Real mode | N/A | N/A | N/A | N/A | 16-bit | 16-bit
Virtual 8086 mode | N/A | N/A | N/A | N/A | 16-bit | 16-bit
Protected mode / Long compatibility mode | 0 | no | no | N/A | 16-bit | 16-bit
 | 0 | no | yes | N/A | 16-bit | 32-bit
 | 0 | yes | no | N/A | 32-bit | 16-bit
 | 0 | yes | yes | N/A | 32-bit | 32-bit
 | 1 | no | no | N/A | 32-bit | 32-bit
 | 1 | no | yes | N/A | 32-bit | 16-bit
 | 1 | yes | no | N/A | 16-bit | 32-bit
 | 1 | yes | yes | N/A | 16-bit | 16-bit
Long 64-bit mode | ignored | no | no | 0 | 32-bit | 64-bit
 | ignored | no | yes | 0 | 32-bit1 | 32-bit
 | ignored | yes | no | 0 | 16-bit | 64-bit
 | ignored | yes | yes | 0 | 16-bit | 32-bit
 | ignored | ignored | no | 1 | 64-bit1 | 64-bit
 | ignored | ignored | yes | 1 | 64-bit | 32-bit

1: Certain instructions default to (or are fixed at) 64-bit operands and do not need the REX prefix for this, see this table.

NASM

NASM determines the operand size by looking at the MODRM.reg or (for a register) MODRM.rm fields. When they are both 32-bit, the operand size becomes 32-bit. Same for 16-bit and 64-bit. When they differ, an error occurs at compile time. The address size is determined by looking at (for a memory operand) the MODRM.rm field, or the SIB.base, SIB.index and displacement, in that order. So when SIB.base uses a 16-bit register (such as AX), the address size becomes 16-bit. Using a 32-bit displacement will result in the displacement being truncated.

Opcode

The x86-64 instruction set defines many opcodes and many ways to encode them, depending on several factors.

Legacy opcodes

Legacy (and x87) opcodes consist of, in this order:

  • mandatory prefix;
  • REX prefix;
  • opcode.

Mandatory prefix

Certain instructions (most notably the SIMD instructions) require a mandatory prefix (0x66, 0xF2 or 0xF3), which looks like a normal modifier prefix. When a mandatory prefix is required, it is put with the modifier prefixes before the REX prefix (if any).

REX prefix

The REX prefix is only available in long mode.

Usage

A REX prefix must be encoded when:

  • using 64-bit operand size and the instruction does not default to 64-bit operand size; or
  • using one of the extended registers (R8 to R15, XMM8 to XMM15, YMM8 to YMM15, CR8 to CR15 and DR8 to DR15); or
  • using one of the uniform byte registers SPL, BPL, SIL or DIL.

A REX prefix must not be encoded when:

  • using one of the high byte registers AH, CH, BH or DH.

In all other cases, the REX prefix is ignored. The use of multiple REX prefixes is undefined, although processors seem to use only the last REX prefix.

Instructions that default to 64-bit operand size in long mode are:

CALL (near) | ENTER | Jcc
JrCXZ | JMP (near) | LEAVE
LGDT | LIDT | LLDT
LOOP | LOOPcc | LTR
MOV CR(n) | MOV DR(n) | POP reg/mem
POP reg | POP FS | POP GS
POPFQ | PUSH imm8 | PUSH imm32
PUSH reg/mem | PUSH reg | PUSH FS
PUSH GS | PUSHFQ | RET (near)
Encoding
The layout is as follows:

  7                           0
┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 0 │ 1 │ 0 │ 0 │ W │ R │ X │ B │
└───┴───┴───┴───┴───┴───┴───┴───┘

Field | Length | Description
b0100 | 4 bits | Fixed bit pattern
W | 1 bit | When 1, a 64-bit operand size is used. Otherwise, when 0, the default operand size is used (which is 32-bit for most but not all instructions, see this table).
R | 1 bit | This 1-bit value is an extension to the MODRM.reg field. See Registers.
X | 1 bit | This 1-bit value is an extension to the SIB.index field. See 64-bit addressing.
B | 1 bit | This 1-bit value is an extension to the MODRM.rm field or the SIB.base field. See 64-bit addressing.

Opcode

The opcode can be 1, 2 or 3 bytes in length. Depending on the opcode escape sequence, a different opcode map is selected. Possible opcode sequences are:

  • <op>
  • 0x0F <op>
  • 0x0F 0x38 <op>
  • 0x0F 0x3A <op>

Note that opcodes can specify that the REG field in the ModR/M byte is fixed at a particular value.

VEX/XOP opcodes

A VEX/XOP prefix must be encoded when:

  • the instruction has only its VEX/XOP opcode and no legacy opcode; or
  • 256-bit YMM registers are used; or
  • more than three operands are used (e.g. nondestructive-source operations); or
  • when using 128-bit XMM destination registers, bits 128-255 of the corresponding YMM register must be cleared.

A VEX/XOP prefix must not be encoded when:

  • when using 128-bit XMM destination registers, bits 128-255 of the corresponding YMM register must not be changed.

There are many VEX and XOP instructions, all of which can be encoded using the three byte VEX/XOP escape prefix. The VEX and XOP escape prefixes use fields with the following semantics:

Field | Length | Description
VEX/XOP prefix 8 bits Prefix.
Prefix | Opcode map and encoding
0xC4 | Three-byte VEX
0xC5 | Two-byte VEX
0x8F | Three-byte XOP
~R | 1 bit | This 1-bit value is an 'inverted' extension to the MODRM.reg field. The inverse of REX.R. See Registers.
~X | 1 bit | This 1-bit value is an 'inverted' extension to the SIB.index field. The inverse of REX.X. See 64-bit addressing.
~B | 1 bit | This 1-bit value is an 'inverted' extension to the MODRM.rm field or the SIB.base field. The inverse of REX.B. See 64-bit addressing.
map_select | 5 bits | Specifies the opcode map to use.
W/E | 1 bit | For integer instructions: when 1, a 64-bit operand size is used; otherwise, when 0, the default operand size is used (equivalent with REX.W). For non-integer instructions, this bit is a general opcode extension bit.
~vvvv | 4 bits | An additional operand for the instruction. The value of the XMM or YMM register (see Registers) is 'inverted'.
L | 1 bit | When 0, a 128-bit vector lengh is used. Otherwise, when 1, a 256-bit vector length is used.
pp 2 bits Specifies an implied mandatory prefix for the opcode.
Value | Implied mandatory prefix
b00 | none
b01 | 0x66
b10 | 0xF3
b11 | 0xF2

Three byte VEX escape prefix

The layout is as follows, starting with a byte with value 0xC4:

  7                           0       7                           0     7                           0
+---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
| 1   1   0   0   0   1   0   0 |   |~R |~X |~B |     map_select    |   |W/E|     ~vvvv     | L |   pp  |
+---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+

A VEX instruction whose values for certain fields are VEX.~X == 1, VEX.~B == 1, VEX.W/E == 0 and map_select == b00001 may be encoded using the two byte VEX escape prefix.

Three byte XOP escape prefix

The layout is the same as the three-byte VEX escape prefix, but with initial byte value 0x8F:

  7                           0       7                           0     7                           0
+---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
| 1   0   0   0   1   1   1   1 |   |~R |~X |~B |     map_select    |   |W/E|     ~vvvv     | L |   pp  |
+---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+

Two byte VEX escape prefix

A VEX instruction whose values for certain fields are VEX.~X == 1, VEX.~B == 1, VEX.W/E == 0 and map_select == b00001 may be encoded using the two byte VEX escape prefix. The layout is as follows:

  7                           0       7                           0
+---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
| 1   1   0   0   0   1   0   1 |   |~R |     ~vvvv     | L |   pp  |
+---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+

3DNow! opcodes

3DNow! opcodes consist of, in this order:

  • fixed opcode;
  • (ModR/M, SIB, displacement);
  • immediate opcode byte.

Fixed opcode

All 3DNow! opcodes have a fixed two-byte sequence equal to 0x0F 0x0F in the opcode position of the instruction.

Immediate opcode byte

3DNow! instructions encode the actual opcode as an 8-bit immediate value trailing the instruction (thus after the ModR/M, SIB and displacement).

ModR/M and SIB bytes

The ModR/M and SIB bytes are used to encode up to two operands of an instruction, each of which is a direct register or effective memory address.

ModR/M

The ModR/M byte encodes a register or an opcode extension, and a register or a memory address. It has the following fields:

  7                           0
+---+---+---+---+---+---+---+---+
|  mod  |    reg    |     rm    |
+---+---+---+---+---+---+---+---+
Field | Length | Description
MODRM.mod | 2 bits | In general, when this field is b11, then register-direct addressing mode is used; otherwise register-indirect addressing mode is used.
MODRM.reg 3 bits This field can have one of two values:
  • A 3-bit opcode extension, which is used by some instructions but has no further meaning other than distinguishing the instruction from other instructions.
  • A 3-bit register reference, which can be used as the source or the destination of an instruction (depending on the instruction). The referenced register depends on the operand-size of the instruction and the instruction itself. See Registers for the values to use for each of the registers. The REX.R, VEX.~R or XOP.~R field can extend this field with 1 most-significant bit to 4 bits total.
MODRM.rm | 3 bits | Specifies a direct or indirect register operand, optionally with a displacement. The REX.B, VEX.~B or XOP.~B field can extend this field with 1 most-significant bit to 4 bits total.

16-bit addressing

These are the meanings of the Mod (vertically) and REX/VEX/XOP.B and R/M bits (horizontally) for 16-bit addressing. B.R/M and Mod are in binary. The SIB-byte is not used in 16-bit addressing. In Long processing mode there is no way to specify 16-bit addresses.

16-bit | B.R/M
Mod | x.000 AX, R8W | x.001 CX, R9W | x.010 DX, R10W | x.011 BX, R11W | x.100 SP, R12W | x.101 BP, R13W | x.110 SI, R14W | x.111 DI, R15W
00 | [BX + SI] | [BX + DI] | [BP + SI] | [BP + DI] | [SI] | [DI] | [disp16] | [BX]
01 | [BX + SI + disp8] | [BX + DI + disp8] | [BP + SI + disp8] | [BP + DI + disp8] | [SI + disp8] | [DI + disp8] | [BP + disp8] | [BX + disp8]
10 | [BX + SI + disp16] | [BX + DI + disp16] | [BP + SI + disp16] | [BP + DI + disp16] | [SI + disp16] | [DI + disp16] | [BP + disp16] | [BX + disp16]
11 | r/m

32/64-bit addressing

These are the meanings of the Mod (vertically) and REX/VEX/XOP.B and R/M bits (horizontally) for 32 and 64-bit addressing. B.R/M and Mod are in binary.

32/64-bit | B.R/M
Mod | 0.000 AX | 0.001 CX | 0.010 DX | 0.011 BX | 0.100 SP | 0.101 BP | 0.110 SI | 0.111 DI | 1.000 R8 | 1.001 R9 | 1.010 R10 | 1.011 R11 | 1.100 R12 | 1.101 R13 | 1.110 R14 | 1.111 R15
00 | [r/m] |  |  |  | [SIB] | [RIP/EIP 1,2 + disp32] | [r/m] |  |  |  |  |  | [SIB] | [RIP/EIP 1,2 + disp32] | [r/m]
01 | [r/m + disp8] |  |  |  | [SIB + disp8] | [r/m + disp8] |  |  |  |  |  |  | [SIB + disp8] | [r/m + disp8]
10 | [r/m + disp32] |  |  |  | [SIB + disp32] | [r/m + disp32] |  |  |  |  |  |  | [SIB + disp32] | [r/m + disp32]
11 | r/m

1: In protected/compatibility mode, this is just disp32, but in long mode this is [RIP]+disp32 (for 64-bit addresses) or [EIP]+disp32 (for 32-bit addresses, i.e. with address-size override prefix, see here).
2: In long mode, to encode disp32 as in protected/compatibility mode, use the SIB byte.

RIP/EIP-relative addressing

Addressing in x86-64 can be relative to the current instruction pointer value. This is indicated with the RIP (64-bit) and EIP (32-bit) instruction pointer registers, which are not otherwise exposed to the program and may not exist physically. RIP-relative addressing allows object files to be location independent.

SIB

The SIB byte has the following fields:

  7                           0
+---+---+---+---+---+---+---+---+
| scale |   index   |    base   |
+---+---+---+---+---+---+---+---+
Field | Length | Description
SIB.scale 2 bits This field indicates the scaling factor of SIB.index, where s (as used in the tables) equals 2SIB.scale.
SIB.scale | factor s
b00 | 1
b01 | 2
b10 | 4
b11 | 8
SIB.index | 3 bits | The index register to use. See Registers for the values to use for each of the registers. The REX.X, VEX.~X or XOP.~X field can extend this field with 1 most-significant bit to 4 bits total.
SIB.base | 3 bits | The base register to use. See Registers for the values to use for each of the registers. The REX.B, VEX.~B or XOP.~B field can extend this field with 1 most-significant bit to 4 bits total.

32/64-bit addressing

The meaning of the SIB byte while using 32 or 64-bit addressing is as follows. The ModR/M byte's Mod field and the SIB byte's index field are used vertically, the SIB byte's base field and REX/VEX/XOP.B bit horizontally. The s is the scaling factor. B.Base, X.Index and Mod are in binary.

 |  | B.Base
Mod | X.Index | 0.000 AX | 0.001 CX | 0.010 DX | 0.011 BX | 0.100 SP | 0.1011 BP | 0.110 SI | 0.111 DI | 1.000 R8 | 1.001 R9 | 1.010 R10 | 1.011 R11 | 1.100 R12 | 1.1011 R13 | 1.110 R14 | 1.111 R15
00 | 0.000 AX | [base + (index * s)] |  |  |  |  | [(index * s) + disp32] | [base + (index * s)] |  |  |  |  |  |  | [(index * s) + disp32] | [base + (index * s)]
 | 0.001 CX
 | 0.010 DX
 | 0.011 BX
 | 0.1002 SP | [base] |  |  |  |  | [disp32] | [base] |  |  |  |  |  |  | [disp32] | [base]
 | 0.101 BP | [base + (index * s)] |  |  |  |  | [(index * s) + disp32] | [base + (index * s)] |  |  |  |  |  |  | [(index * s) + disp32] | [base + (index * s)]
 | 0.110 SI
 | 0.111 DI
 | 1.000 R8
 | 1.001 R9
 | 1.010 R10
 | 1.011 R11
 | 1.100 R12
 | 1.101 R13
 | 1.110 R14
 | 1.111 R15
 |  | B.Base
Mod | X.Index | 0.000 AX | 0.001 CX | 0.010 DX | 0.011 BX | 0.100 SP | 0.101 BP | 0.110 SI | 0.111 DI | 1.000 R8 | 1.001 R9 | 1.010 R10 | 1.011 R11 | 1.100 R12 | 1.101 R13 | 1.110 R14 | 1.111 R15
01 | 0.000 AX | [base + (index * s) + disp8]
 | 0.001 CX
 | 0.010 DX
 | 0.011 BX
 | 0.1002 SP | [base + disp8]
 | 0.101 BP | [base + (index * s) + disp8]
 | 0.110 SI
 | 0.111 DI
 | 1.000 R8
 | 1.001 R9
 | 1.010 R10
 | 1.011 R11
 | 1.100 R12
 | 1.101 R13
 | 1.110 R14
 | 1.111 R15
 |  | B.Base
Mod | X.Index | 0.000 AX | 0.001 CX | 0.010 DX | 0.011 BX | 0.100 SP | 0.101 BP | 0.110 SI | 0.111 DI | 1.000 R8 | 1.001 R9 | 1.010 R10 | 1.011 R11 | 1.100 R12 | 1.101 R13 | 1.110 R14 | 1.111 R15
10 | 0.000 AX | [base + (index * s) + disp32]
 | 0.001 CX
 | 0.010 DX
 | 0.011 BX
 | 0.1002 SP | [base + disp32]
 | 0.101 BP | [base + (index * s) + disp32]
 | 0.110 SI
 | 0.111 DI
 | 1.000 R8
 | 1.001 R9
 | 1.010 R10
 | 1.011 R11
 | 1.100 R12
 | 1.101 R13
 | 1.110 R14
 | 1.111 R15

1: No base register is encoded.
2: No index register is encoded.

Displacement

A displacement value is a 1, 2, 4, or 8 byte offset added to the calculated address. When an 8 byte displacement is used, no immediate operand is encoded.

The displacement value, if any, follows the ModR/M and SIB bytes discussed above. When the ModR/M or SIB tables state that a disp value is required, or without a ModR/M byte the use of moffset (AMD) or moffs (Intel) in the mnemonic syntax of the instruction, then the displacement bytes are required.

Immediate

Some instructions require an immediate value. The instruction (and the operand-size column in the above table) determine the length of the immediate value. The imm8 mnemonic (or 8-bit operand-size) means a one byte immediate value, imm16 (or 16-bit operand-size) means a two byte immediate value, imm32 (or 32-bit operand-size) a four byte value and imm64 (or 64-bit operand-size) an eight byte value. When an 8 byte immediate value is encoded, no displacement can be encoded.

See Also

External References

  • AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions
  • Intel 64 and IA-32 Architectures Software Developer's Manuals
Retrieved from "http://wiki.osdev.org/index.php?title=X86-64_Instruction_Encoding&oldid=13875"
  • X86 CPU