1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
* x86_64
[[./flowchart.png]]
(optional) legacy prefixes
-> (optional) REX prefix
-> primary opcode
-> (optional) ModRM
-> (optional) SIB
-> (optional) displacement
-> (optional) immediate
** Legacy prefixes (up to 5)
*** 0x66 - operand-size override
Makes operand size 16-bit instead of default 32-bit.
(REX.W has higher priority and makes operand size 64-bit.)
*** 0x67 - address-size override
Makes address size 32-bit instead of default 64-bit.
** REX
0x40 through 0x4f
Low bits:
3 2 1 0
W R X B
When W = 1, the operand size is 64-bits (RAX instead of EAX, etc.)
R is used as an extra high bit for the ModRM reg field (to indicate regs R8 through R15)
X is used as an extra high bit for the SIB index register
B is used as an extra high bit for the SIB base register, ModRM r/m field, or an opcode-specific reg field
** primary opcode map
Operand notation
*** Location
E - general purpose register or memory specified by ModRM.r/m / SIB
F - rFLAGS register
G - general purpose register specified by ModRM.reg
I - immediate value encoded in the immediate field
J - instruction encoding includes a relative offset added to rIP
M - memory specified by mod and r/m in ModRM. ModRM.mod /= 0b11
O - offset of an operand is encoded in the instruction. no ModRM
R - general purpose register specified by ModRM.r/m. ModRM.mod == 0b11
*** Type
b - a byte
c - a byte or 2 bytes, depending on effective operand size
d - 4 bytes
i - a 16-bit integer
j - a 32-bit integer
m - a bit mask of size equal to source
mn - where n = 2,4,8, or 16: a bit mask of size n
q - 8 bytes
v - 2 bytes, 4 bytes, or 8 bytes, depending on effective operand size
w - 2 bytes
y - 4 bytes or 8 bytes depending on effective operand size
z - 2 bytes if the effective operand size is 16 bits, or 4 bytes if the effective operand size is 32 or 64 bits
** ModRM
Used to specify either 2 register operands or 1 register and 1 memory operand.
Three fields: MOD, REG, and R/M
When REX prefix is present, REX.R is used as a high bit on REG and REX.B is used as a high bit on R/M
7 6 5 4 3 2 1 0
MOD REG-- R/M--
When MOD is 0b11, both REG and R/M denote registers as follows
| 000 | rAX, XMM0, etc. |
| 001 | rCX, XMM1, etc. |
| 010 | rDX, XMM2, etc. |
| 011 | rBX, XMM3, etc. |
| 100 | AH, rSP, XMM4, etc. |
| 101 | CH, rBP, XMM5, etc. |
| 110 | DH, rSI, XMM6, etc. |
| 111 | BH, rDI, XMM7, etc. |
(When REX prefix is specified, REX.R is an extra high bit that allows access to registers 8 through 15)
When MOD is not 0b11, R/M denotes a base register for memory access
| 000 | [rAX] |
| 001 | [rCX] |
| 010 | [rDX] |
| 011 | [rBX] |
| 100 | see SIB byte |
| 101 | [rBP] or [RIP] if MOD = 0b00 (even if REX.B is 1!!!) |
| 110 | [rSI] |
| 111 | [rDI] |
The offset from the base register is determined by the displacement bytes (these follow SIB)
If MOD is 01 there is a 1-byte displacement, if MOD is 10 there is a 4-byte displacement
** SIB
Occurs only after ModRM
** Displacement
A displacement is a signed offset from a base used to indicate a memory address.
Either 1 or 4 bytes depending on MOD, sign-extended to 64 bits during address calculation.
** Immediate
Either 1, 2, 4, or 8 (only for MOV into GPR) bytes.
|