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):
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:
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).
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):
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:401b ca rex sbb ecx,edx
5:411b ca rex.B sbb ecx,r10d
8:421b ca rex.X sbb ecx,edx
b: 431b ca rex.XB sbb ecx,r10d
e: 441b ca rex.R sbb r9d,edx
11:451b ca rex.RB sbb r9d,r10d
14:461b ca rex.RX sbb r9d,edx
17:471b ca rex.RXB sbb r9d,r10d
1a: 481b 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:290491 sub DWORD PTR [rcx+rdx*4],eax
3:40290491 rex sub DWORD PTR [rcx+rdx*4],eax
7:41290491 rex.B sub DWORD PTR [r9+rdx*4],eax
b: 42290491 rex.X sub DWORD PTR [rcx+r10*4],eax
f: 43290491 rex.XB sub DWORD PTR [r9+r10*4],eax
13:44290491 rex.R sub DWORD PTR [rcx+rdx*4],r8d
17:45290491 rex.RB sub DWORD PTR [r9+rdx*4],r8d
1b: 46290491 rex.RX sub DWORD PTR [rcx+r10*4],r8d
1f: 47290491 rex.RXB sub DWORD PTR [r9+r10*4],r8d
23:48290491 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):
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):
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:210525000010 and DWORD PTR [rip+0x10000025],eax
6:40210525000010 rex and DWORD PTR [rip+0x10000025],eax
d: 41210525000010 rex.B and DWORD PTR [rip+0x10000025],eax
14:42210525000010 rex.X and DWORD PTR [rip+0x10000025],eax
1b: 43210525000010 rex.XB and DWORD PTR [rip+0x10000025],eax
22:44210525000010 rex.R and DWORD PTR [rip+0x10000025],r8d
29:45210525000010 rex.RB and DWORD PTR [rip+0x10000025],r8d
30:46210525000010 rex.RX and DWORD PTR [rip+0x10000025],r8d
37:47210525000010 rex.RXB and DWORD PTR [rip+0x10000025],r8d
3e: 48210525000010 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):
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: