Table of contents

Abstract

On an Intel or AMD processor, when executing code from a 64-bit code segment (i.e., CS segment descriptor CS[L] bit = 1b and CS[D] = 0b), the 1-byte REX (i.e., Register eXtended) prefix can be used to modify operand addressing and selection. This can be for one of the following reasons:

  • Specify the 64-bit version of the legacy GPRs (General Purpose Registers): RAX, RCX, RDX, RBX, RBP, ESP, RSI or RDI;
  • Specify the extended registers: R6-R15 or XMM8-XMM15;
  • The new 1-byte SPL, BPL, SIL and DIL registers; and
  • When using a 64-bit operand

According to the Intel developer manual, the REX prefix encoded (between 40h-4Fh) as follows:

Field Name Bit Position Definition
- 7:4 0100b
W 3 0 = Operand size determined by CS[D] 1 = 64 Bit Operand Size
R 2 Extension of ModRM[reg]
X 1 Extension of SIB[index]
B 0 Extension of ModRM[rm], SIB[base] or Opcode[reg]

It is not because the REX prefix is encoded in the instruction that it will necessarily alter the instruction. In other words, it means that if the REX prefix is added to the instruction, but the different fields are empty or not related to the operands upon which the instruction will operate – it will do nothing. As a result, it is possible to identify the following cases:

  • Case 1: 40h-47h
    • opcode
    • opcode + ModRM disp32
  • Case 2: 40h, 42h, 44h and 46h
    • opcode + opcode[reg] + imm
    • opcode + ModRM[reg] + imm
  • Case 3: 40h, 41h, 44h and 45h
    • opcode + ModRM + SIB w/o base + imm
  • Case 4: 40h and 42h
    • opcode + ModRM reg/rm
    • opcode + ModRM reg/reg
  • Case 5: 40h
    • opcode + ModRM + SIB
    • opcode + ModRM + SIB w/o index
    • opcode + ModRM + SIB w/o index + imm
  • Case 6: 40h, 41h, 42h and 43h
    • opcode + ModRM disp32
  • Case 7: 40h and 41h
    • opcode + ModRM + SIB w/o base

Please note, all examples provided here are for instructions operating upon General Purpose Registers (GPRs). x87 FP, MMX and AVX are not treated here.

Case 1

Instruction encoded with no ModRM byte (and therefore no SIB byte as well), no immediate data value, not displacement and no register encoded in the 3 LSB (i.e., less-significant bits) of the primary opcode (e.g., LODS – ADh):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  ad                              lods eax,DWORD PTR ds:[rsi]
1:  40 ad                   rex     lods eax,DWORD PTR ds:[rsi]
3:  41 ad                   rex.B   lods eax,DWORD PTR ds:[rsi]
5:  42 ad                   rex.X   lods eax,DWORD PTR ds:[rsi]
7:  43 ad                   rex.XB  lods eax,DWORD PTR ds:[rsi]
9:  44 ad                   rex.R   lods eax,DWORD PTR ds:[rsi]
b:  45 ad                   rex.RB  lods eax,DWORD PTR ds:[rsi]
d:  46 ad                   rex.RX  lods eax,DWORD PTR ds:[rsi]
f:  47 ad                   rex.RXB lods eax,DWORD PTR ds:[rsi]
11: 48 ad                   rex.W   lods rax,QWORD PTR ds:[rsi]

Instruction with an 8-, 16-, 32- or 64-bit immediate data value and a register (e.g., MOV – C7h). Encoded with a ModRM byte that define a 32-bit displacement (i.e., ModRM[mod] == 00b and ModRM[rm] == 101b):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  c7 05 00 00 00 00 44 33 22 11              mov DWORD PTR [rip+0x0],0x11223344
a:  40 c7 05 00 00 00 00 44 33 22 11   rex     mov DWORD PTR [rip+0x0],0x11223344
15: 41 c7 05 00 00 00 00 44 33 22 11   rex.B   mov DWORD PTR [rip+0x0],0x11223344
20: 42 c7 05 00 00 00 00 44 33 22 11   rex.X   mov DWORD PTR [rip+0x0],0x11223344
2b: 43 c7 05 00 00 00 00 44 33 22 11   rex.XB  mov DWORD PTR [rip+0x0],0x11223344
36: 44 c7 05 00 00 00 00 44 33 22 11   rex.R   mov DWORD PTR [rip+0x0],0x11223344
41: 45 c7 05 00 00 00 00 44 33 22 11   rex.RB  mov DWORD PTR [rip+0x0],0x11223344
4c: 46 c7 05 00 00 00 00 44 33 22 11   rex.RX  mov DWORD PTR [rip+0x0],0x11223344
57: 47 c7 05 00 00 00 00 44 33 22 11   rex.RXB mov DWORD PTR [rip+0x0],0x11223344
62: 48 c7 05 00 00 00 00 44 33 22 11   rex.W   mov QWORD PTR [rip+0x0],0x11223344

Case 2

Instruction with 8-, 16-, 32- or 64-bit immediate data value and a register (e.g., MOV B8h) and the destination register is encoded in the 3 LSBs of the primary opcode:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  b8 11 22 33 44                          mov eax,0x44332211
5:  40 b8 11 22 33 44               rex     mov eax,0x44332211
b:  41 b8 11 22 33 44               rex.B   mov r8d,0x44332211
11: 42 b8 11 22 33 44               rex.X   mov eax,0x44332211
17: 43 b8 11 22 33 44               rex.XB  mov r8d,0x44332211
1d: 44 b8 11 22 33 44               rex.R   mov eax,0x44332211
23: 45 b8 11 22 33 44               rex.RB  mov r8d,0x44332211
29: 46 b8 11 22 33 44               rex.RX  mov eax,0x44332211
2f: 47 b8 11 22 33 44               rex.RXB mov r8d,0x44332211
35: 48 b8 11 22 33 44 55 66 77 88   rex.W   mov rax,0x8877665544332211 

Instruction with 8-, 16-, 32- or 64-bit immediate data value and a register (e.g., ROR – C1h). Encoded with a ModRM byte. The ModRM[rm] filed being used to identify an instruction from a micro-map (i.e., opcode extension/groups).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  c1 c8 08                        ror eax,0x8
3:  40 c1 c8 08             rex     ror eax,0x8
7:  41 c1 c8 08             rex.B   ror r8d,0x8
b:  42 c1 c8 08             rex.X   ror eax,0x8
f:  43 c1 c8 08             rex.XB  ror r8d,0x8
13: 44 c1 c8 08             rex.R   ror eax,0x8
17: 45 c1 c8 08             rex.RB  ror r8d,0x8
1b: 46 c1 c8 08             rex.RX  ror eax,0x8
1f: 47 c1 c8 08             rex.RXB ror r8d,0x8
23: 48 c1 c8 08             rex.W   ror rax,0x8

Case 3

Instruction with 16-, 32- or 64-bit immediate data value and a register (e.g., MOV C7h). Encoded with a ModRM byte and a SIB byte without a base register (i.e., SIB[base] = 101b):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  c7 04 5d 00 00 00 00 44 33 22 11              mov DWORD PTR [rbx*2+0x0],0x11223344
b:  40 c7 04 5d 00 00 00 00 44 33 22 11   rex     mov DWORD PTR [rbx*2+0x0],0x11223344
17: 41 c7 04 5d 00 00 00 00 44 33 22 11   rex.B   mov DWORD PTR [rbx*2+0x0],0x11223344
23: 42 c7 04 5d 00 00 00 00 44 33 22 11   rex.X   mov DWORD PTR [r11*2+0x0],0x11223344
2f: 43 c7 04 5d 00 00 00 00 44 33 22 11   rex.XB  mov DWORD PTR [r11*2+0x0],0x11223344
3b: 44 c7 04 5d 00 00 00 00 44 33 22 11   rex.R   mov DWORD PTR [rbx*2+0x0],0x11223344
47: 45 c7 04 5d 00 00 00 00 44 33 22 11   rex.RB  mov DWORD PTR [rbx*2+0x0],0x11223344
53: 46 c7 04 5d 00 00 00 00 44 33 22 11   rex.RX  mov DWORD PTR [r11*2+0x0],0x11223344
5f: 47 c7 04 5d 00 00 00 00 44 33 22 11   rex.RXB mov DWORD PTR [r11*2+0x0],0x11223344
6b: 48 c7 04 5d 00 00 00 00 44 33 22 11   rex.W   mov QWORD PTR [rbx*2+0x0],0x11223344

Case 4

Instruction with no immediate data value and a displacement (e.g., ADC – 11h). Encoded with a ModRM byte and no SIB byte:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  11 01                           adc DWORD PTR [rcx],eax
2:  40 11 01                rex     adc DWORD PTR [rcx],eax
5:  41 11 01                rex.B   adc DWORD PTR [r9],eax
8:  42 11 01                rex.X   adc DWORD PTR [rcx],eax
b:  43 11 01                rex.XB  adc DWORD PTR [r9],eax
e:  44 11 01                rex.R   adc DWORD PTR [rcx],r8d
11: 45 11 01                rex.RB  adc DWORD PTR [r9],r8d
14: 46 11 01                rex.RX  adc DWORD PTR [rcx],r8d
17: 47 11 01                rex.RXB adc DWORD PTR [r9],r8d
1a: 48 11 01                rex.W   adc QWORD PTR [rcx],rax

Instruction with no immediate value and register to register operation (e.g., SBB – 1Bh). Encoded with a ModRM byte and no SIB byte.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  1b ca                           sbb ecx,edx
2:  40 1b ca                rex     sbb ecx,edx
5:  41 1b ca                rex.B   sbb ecx,r10d
8:  42 1b ca                rex.X   sbb ecx,edx
b:  43 1b ca                rex.XB  sbb ecx,r10d
e:  44 1b ca                rex.R   sbb r9d,edx
11: 45 1b ca                rex.RB  sbb r9d,r10d
14: 46 1b ca                rex.RX  sbb r9d,edx
17: 47 1b ca                rex.RXB sbb r9d,r10d
1a: 48 1b ca                rex.W   sbb rcx,rdx

Case 5

Instruction with no immediate data value and a displacement (e.g., SUB – 29h). Encoded with a ModRM byte and a SIB byte:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  29 04 91                        sub DWORD PTR [rcx+rdx*4],eax
3:  40 29 04 91             rex     sub DWORD PTR [rcx+rdx*4],eax
7:  41 29 04 91             rex.B   sub DWORD PTR [r9+rdx*4],eax
b:  42 29 04 91             rex.X   sub DWORD PTR [rcx+r10*4],eax
f:  43 29 04 91             rex.XB  sub DWORD PTR [r9+r10*4],eax
13: 44 29 04 91             rex.R   sub DWORD PTR [rcx+rdx*4],r8d
17: 45 29 04 91             rex.RB  sub DWORD PTR [r9+rdx*4],r8d
1b: 46 29 04 91             rex.RX  sub DWORD PTR [rcx+r10*4],r8d
1f: 47 29 04 91             rex.RXB sub DWORD PTR [r9+r10*4],r8d
23: 48 29 04 91             rex.W   sub QWORD PTR [rcx+rdx*4],rax

Instruction with no immediate data value and a displacement (e.g., CMP 39h). Encoded with a ModRM and a SIB byte without index (i.e., SIB[index] == 100b):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  39 04 e1                        cmp DWORD PTR [rcx*8],eax
3:  40 39 04 e1             rex     cmp DWORD PTR [rcx*8],eax
7:  41 39 04 e1             rex.B   cmp DWORD PTR [r9*8],eax
b:  42 39 04 e1             rex.X   cmp DWORD PTR [rcx+r12*8],eax
f:  43 39 04 e1             rex.XB  cmp DWORD PTR [r9+r12*8],eax
13: 44 39 04 e1             rex.R   cmp DWORD PTR [rcx*8],r8d
17: 45 39 04 e1             rex.RB  cmp DWORD PTR [r9*8],r8d
1b: 46 39 04 e1             rex.RX  cmp DWORD PTR [rcx+r12*8],r8d
1f: 47 39 04 e1             rex.RXB cmp DWORD PTR [r9+r12*8],r8d
23: 48 39 04 e1             rex.W   cmp QWORD PTR [rcx*8],rax

Instruction with 8-, 16-, 32- or 64-bit immediate data value and a register (e.g., MOV – C7h). Encoded with a ModRM byte and a SIB byte with no index register (i.e., SIB[index] == 100b):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  c7 04 20 44 33 22 11              mov DWORD PTR [rax],0x11223344
7:  40 c7 04 20 44 33 22 11   rex     mov DWORD PTR [rax],0x11223344
f:  41 c7 04 20 44 33 22 11   rex.B   mov DWORD PTR [r8],0x11223344
17: 42 c7 04 20 44 33 22 11   rex.X   mov DWORD PTR [rax+r12*1],0x11223344
1f: 43 c7 04 20 44 33 22 11   rex.XB  mov DWORD PTR [r8+r12*1],0x11223344
27: 44 c7 04 20 44 33 22 11   rex.R   mov DWORD PTR [rax],0x11223344
2f: 45 c7 04 20 44 33 22 11   rex.RB  mov DWORD PTR [r8],0x11223344
37: 46 c7 04 20 44 33 22 11   rex.RX  mov DWORD PTR [rax+r12*1],0x11223344
3f: 47 c7 04 20 44 33 22 11   rex.RXB mov DWORD PTR [r8+r12*1],0x11223344
47: 48 c7 04 20 44 33 22 11   rex.W   mov QWORD PTR [rax],0x11223344

Case 6

Instruction with no immediate data value and a displacement (e.g., AND – 21h). Encoded with a ModRM byte that define a 32-bit displacement (i.e., ModRM[mod] == 00b and ModRM[rm] == 101b):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  21 05 25 00 00 10               and DWORD PTR [rip+0x10000025],eax
6:  40 21 05 25 00 00 10    rex     and DWORD PTR [rip+0x10000025],eax
d:  41 21 05 25 00 00 10    rex.B   and DWORD PTR [rip+0x10000025],eax
14: 42 21 05 25 00 00 10    rex.X   and DWORD PTR [rip+0x10000025],eax
1b: 43 21 05 25 00 00 10    rex.XB  and DWORD PTR [rip+0x10000025],eax
22: 44 21 05 25 00 00 10    rex.R   and DWORD PTR [rip+0x10000025],r8d
29: 45 21 05 25 00 00 10    rex.RB  and DWORD PTR [rip+0x10000025],r8d
30: 46 21 05 25 00 00 10    rex.RX  and DWORD PTR [rip+0x10000025],r8d
37: 47 21 05 25 00 00 10    rex.RXB and DWORD PTR [rip+0x10000025],r8d
3e: 48 21 05 25 00 00 10    rex.W   and QWORD PTR [rip+0x10000025],rax

Case 7

Instruction with no immediate data value and a displacement (e.g., XOR 33h). Encoded with a ModRM and a SIB byte without base (i.e., SIB[base] == 101b):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:  33 04 5d 00 00 00 00              xor eax,DWORD PTR [rbx*2+0x0]
7:  40 33 04 5d 00 00 00 00   rex     xor eax,DWORD PTR [rbx*2+0x0]
f:  41 33 04 5d 00 00 00 00   rex.B   xor eax,DWORD PTR [rbx*2+0x0]
17: 42 33 04 5d 00 00 00 00   rex.X   xor eax,DWORD PTR [r11*2+0x0]
1f: 43 33 04 5d 00 00 00 00   rex.XB  xor eax,DWORD PTR [r11*2+0x0]
27: 44 33 04 5d 00 00 00 00   rex.R   xor r8d,DWORD PTR [rbx*2+0x0]
2f: 45 33 04 5d 00 00 00 00   rex.RB  xor r8d,DWORD PTR [rbx*2+0x0]
37: 46 33 04 5d 00 00 00 00   rex.RX  xor r8d,DWORD PTR [r11*2+0x0]
3f: 47 33 04 5d 00 00 00 00   rex.RXB xor r8d,DWORD PTR [r11*2+0x0]
47: 48 33 04 5d 00 00 00 00   rex.W   xor rax,QWORD PTR [rbx*2+0x0]

Operand-Size Override Legacy Prefix

Finally, in most cases the REX prefixes between 48h and 4Fh cannot be used; otherwise, they will modify the operand size to 64-bit. However, if the instruction operates on 66-bit operands the Operand Size Override prefix (66h) can be added and will be discarded:

0:  48 83 c8 01                                or rax,0x1
4:  66 48 83 c8 01               data16        or rax,0x1

0:  49 33 04 5d 00 00 00 00             rex.WB xor rax,QWORD PTR [rbx*2+0x0]
8:  66 49 33 04 5d 00 00 00 00   data16 rex.WB xor rax,QWORD PTR [rbx*2+0x0]