x86 architecture opcode encoding
upper case letters |
DREX |
MVEX EVEX |
VEX |
mod R/M |
|
dst |
kkk |
imm.ssss_s' |
v'_vvvv |
reg |
r/m |
r | m |
|
|
|
|
|
|
Mem |
mod != 11 |
|
|
|
B |
G |
E |
R |
GPR |
|
|
|
|
P |
Q |
(PR) N (PR) |
MMX |
VD |
|
L |
H |
V |
W |
(VR) U (VR) |
vector |
|
|
|
vT |
rT |
|
mT |
tile |
|
{K} |
|
vK |
rK |
|
mK |
mask |
|
|
|
|
rB |
|
mB |
bounds |
|
Sreg |
|
Address |
Offset |
|
Creg |
|
|
|
X = [DS:rSI] |
Y = [ES:rDI] |
Dreg |
Flags |
Imm |
Jmp |
Treg |
only Z is left |
lower case letters |
1 |
2 |
4 |
8 |
16 |
32 |
64 |
|
byte |
word |
dword |
qword |
oword |
yword |
zword |
|
|
|
x = oword or yword |
|
[o,y] |
|
upper = yword or zword |
[y,z] |
|
normal = oword or yword or zword |
[o,y,z] |
|
half = qword or oword or yword |
|
[o.q,o,y] |
|
fourth = dword or qword or oword |
|
o.[d,q,o] |
|
eighth = word or dword or qword |
|
o.[w,d,q] |
|
|
v = word or dword or qword |
|
|
z = word or dword or dword |
|
|
y = dword or qword |
|
p = w : [z|v|y] |
a = z : z |
t = {eh} |
colors and annotations |
|
reserved |
internal |
normal |
special |
|
reserved |
internal |
normal |
x86-x64 |
...#mod |
mod can be 0...3 |
...#reg |
reg can be 0...7 |
...#r/m |
r/m can be 0...7 |
...v |
only VEX-encoded form exists |
...I64 |
invalid in PM64 |
...D64 |
defaults to O64 in PM64; 66h results in O16 (implicit RSP references) |
...Df64 |
defaults to O64 in PM64; 66h results in O16 in AMD64 but is ignored in EM64T (near branches) |
...Dv64 |
defaults to O64 in PM64; 66h results in #UD due to VEX encoding (near branches with masks) |
...F64 |
defaults to O64 in PM64; 66h is ignored in AMD64 and EM64T (GDTR/IDTR and CRx/DRx/TRx) |
...+n |
one register explicitly specified, and another n consecutive registers implied |
... |
reg op must be distinct from other reg op(s) (VSIB, AMX INT8/BF16, A512FP16 ADDC/MULC dst) |
instruction encodings |
Fundamentally x86 operands are little-endian and of {transform} ( op {hint} ) {mask} form, arranged in dst,src[,...] order. |
L1OM = {sss,ccccc} ( op {nt} ) {kkk} |
K1OM = {sss} ( op {eh} ) {kkk} |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
1 byte opcodes and 2 byte opcodes |
instruction prefix(es) #1 |
opcode byte(s) |
mod R/M byte 16-bit 32-bit |
SIB byte |
displacement |
immediate #2, #3 |
P1 |
P2 |
P3 |
P4 |
O2 |
O1 |
D1 |
D2 |
D3 |
D4 |
I1 |
I2 |
I3 |
I4 |
SEG, REP, LOCK, 66h, 67h |
0Fh |
xxh |
byte/word/dword |
byte/word/dword |
3 byte opcodes, including DREX |
instruction prefix(es) |
opcode bytes |
mod R/M byte 16-bit 32-bit |
SIB byte |
displacement |
imm |
|
P1 |
P2 |
P3 |
P4 |
O2 |
O1 |
O3 |
D1 |
D2 |
D3 |
D4 |
I1 |
SEG, REP, LOCK, 66h, 67h |
0Fh |
38h |
xxh |
byte/word/dword |
|
3Ah |
byte |
7Ah |
xxh |
|
7Bh |
byte |
VEX2 (C5h), VEX3 (C4h), and XOP (8Fh) |
instruction prefix(es) #4 |
opcode byte |
mod R/M byte 16-bit 32-bit |
SIB byte |
displacement |
imm |
|
P1 |
P2 |
P3 |
P4 |
P5 |
O1 |
D1 |
D2 |
D3 |
D4 |
I1 |
|
SEG, 67h |
C5h |
VEX |
xxh |
byte/word/dword |
byte |
SEG, 67h |
C4h |
VEX1 |
VEX2 |
xxh |
SEG, 67h |
8Fh |
XOP1 |
XOP2 |
xxh |
byte/word/dword |
byte |
byte/word/dword #1 |
L1OM misc (62h) and L1OM vector (D6h) |
instruction prefix(es) |
opcode byte |
mod R/M byte 16-bit 32-bit |
displacement and immediate |
P1 |
P2 |
P3 |
P4 |
P5 |
P6 |
P7 |
O1 |
|
SEG, REP, LOCK, 66h, 67h |
62h |
XBRW and oooo |
I1 |
I2 |
I1 |
I1 |
|
word |
byte |
byte |
SIB byte |
D1 |
D2 |
D3 |
D4 |
|
byte/word/dword |
SEG, REP, LOCK, 66h, 67h |
D6h |
NT, sss, and R'R B'B |
v or c and kkk |
xxh |
D1 |
D2 |
D3 |
D4 |
I1 |
I2 |
byte/word/dword |
word |
MVEX (62h) and EVEX (62h) |
instruction prefix(es) #4 |
opcode byte |
mod R/M byte 16-bit 32-bit |
SIB byte |
displacement |
imm |
|
P1 |
P2 |
P3 |
P4 |
P5 |
P6 |
O1 |
D1 |
D2 |
D3 |
D4 |
I1 |
SEG, 67h |
62h |
MVEX1 |
MVEX2 |
MVEX3 |
xxh |
byte/word/dword |
byte |
EVEX1 |
EVEX2 |
EVEX3 |
DREX |
instruction prefix(es) #5 |
opcode bytes |
mod R/M byte 16-bit 32-bit |
SIB byte |
DREX byte |
displacement |
imm |
|
P1 |
P2 |
P3 |
P4 |
O2 |
O1 |
O3 |
D1 |
D2 |
D3 |
D4 |
I1 |
SEG, REP, LOCK, 66h, 67h |
0Fh |
24h |
xxh |
byte/word/dword |
|
25h |
byte |
notes |
descriptions |
#1 |
In some cases it is possible to encode valid instructions that exceed the traditional 15-byte length limit. For example:
; 16-bit mode
F2 F0 36 66 67 81 84 24 disp32 imm32 = xacquire lock add [ss:esp*1+disp32],imm32
F3 F0 36 66 67 81 84 24 disp32 imm32 = xrelease lock add [ss:esp*1+disp32],imm32
; 16-bit mode
36 67 8F EA 78 12 84 24 disp32 imm32 = lwpins eax,[ss:esp*1+disp32],imm32
36 67 8F EA 78 12 8C 24 disp32 imm32 = lwpval eax,[ss:esp*1+disp32],imm32
36 67 8F EA 78 10 84 24 disp32 imm32 = bextr eax,[ss:esp*1+disp32],imm32
; 64-bit mode
64 67 8F EA F8 12 84 18 disp32 imm32 = lwpins rax,[fs:eax+ebx+disp32],imm32
64 67 8F EA F8 12 8C 18 disp32 imm32 = lwpval rax,[fs:eax+ebx+disp32],imm32
64 67 8F EA F8 10 84 18 disp32 imm32 = bextr rax,[fs:eax+ebx+disp32],imm32
It is up to the user to avoid these cases (and the resulting #GP exception).
|
#2 |
Most 3DNow! instructions use the immediate byte as a third opcode byte. |
#3 |
Some SSE/SSE2 instructions use the immediate byte as a condition code. |
#4 |
The use of a REPE, REPNE, 66h, or REX prefix will result in a #UD exception. |
#5 |
The use of a REX prefix will result in a #UD exception. The DREX byte is used instead. |
byte encodings |
type |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
mod R/M and SIB |
mod |
reg |
r/m |
|
scale |
index |
base |
|
|
|
|
REX |
0100b = 4xh |
W |
R |
X |
B |
|
the REX prefix must immediately precede the opcode byte(s) |
|
|
DREX |
D |
dst (VD) |
O C 0 |
R |
X |
B |
|
OC0=0 for reg,r/m
OC0=1 for r/m,reg
|
outside PM64, DREX.[DRXB] are silently ignored if set to 1 |
|
|
L1OM (misc) |
0110_0010b = 62h |
|
X |
B |
R |
W |
oooo |
|
|
|
|
L1OM (vector) |
1101_0110b = D6h |
|
N T |
sss |
R' |
R |
B' or X |
B |
|
vvvvv or ccccc |
kkk |
|
|
VEX2 |
1100_0101b = C5h |
|
R |
vvvv |
L |
pp |
|
mmmmm = 00001b is implied for VEX2 |
|
|
VEX3 |
1100_0100b = C4h |
|
R |
X |
B |
mmmmm |
|
W |
vvvv |
L |
pp |
|
|
MVEX |
0110_0010b = 62h |
|
R |
X |
B |
R' |
mmmm |
|
W |
vvvv |
0 |
pp |
|
E |
sss |
v' |
kkk |
EVEX |
0110_0010b = 62h |
|
R |
X |
B |
R' |
0 |
mmm |
|
W |
vvvv |
1 |
pp |
|
z |
LL or RC |
b |
v' |
aaa |
XOP |
1000_1111b = 8Fh |
|
R |
X |
B |
mmmmm |
|
W |
vvvv |
L |
pp |
|
|
fields |
descriptions |
inverted |
bits are stored inverted |
W |
0 = default operand size
1 = 64-bit operand size
|
R' and R |
mod R/M byte reg field extension |
X |
SIB byte index field extension
mod R/M byte r/m field extension (for SIB-less MVEX/EVEX)
|
B |
mod R/M byte r/m field extension
SIB byte base field extension
opcode byte reg field extension
|
v' |
VEX prefix vvvv field extension
SIB byte index field extension (for VSIB with MVEX/EVEX)
|
m |
VEX = 000_00b (1-byte map), 000_01b (2-byte map), 000_10b (0Fh,38h), 000_11b (0Fh,3Ah)
VEX = 001_00b (reserved), 001_01b (MAP5 for 2-byte map), 001_10b (MAP6 for 0Fh,38h), 001_11b (reserved)
XOP = 01000b (XOP 8 with imm), 01001b (XOP 9 without imm), 01010b (XOP A with imm)
|
pp |
00b (none), 01b (66h), 10b (F3h), 11b (F2h) |
LL or RC |
00b (128-bit), 01b (256-bit), 10b (512-bit), 11b (reserved) or 00b (RN), 01b (RD), 10b (RU), 11b (RZ) |
|