如何解释 x86 操作码映射?

How to interpret x86 opcode map?

在查看像这样的 x86 操作码映射时:

http://www.mlsite.net/8086/#tbl_map1

它定义映射,例如:

00: ADD Eb,Gb
01: ADD Ev,Gv
...

那 link 对字母的含义有基本的描述,例如:

  • E: A ModR/M byte follows the opcode and specifies the operand. The operand is either a general-purpose register or a memory address. If it is a memory address, the address is computed from a segment register and any of the following values: a base register, an index register, a displacement.
  • b: Byte argument.

但是有点太模糊了。您实际上如何将其转换为 "complete opcode"(整个指令 + 操作码中的参数)?也没能从 Intel manuals 中弄清楚,也许我找错地方了(而且有点不知所措)?看到一个显示输入指令的输出操作码的片段(以及你是如何做到的)会非常有帮助。

一定要使用intel手册。对于每条指令,它都给出了机器代码,第 2 章对指令格式进行了非常详细的描述。

但为了给您一个演练,让我们看看 ADD EDX, [EBX+ECX*4+15h]。 首先,我们通读了 2 指令格式3.1 解释指令参考页 章节,以了解我们将看到的内容。我们对 Opcode Summary 3.1.1.3 Instruction Column Table.

中列出的缩写特别感兴趣

有了这些信息,我们转到描述 ADD 指令的页面,并尝试为我们要编码的指令确定合适的版本。我们的第一个操作数是一个 32 位寄存器,第二个是一个 32 位内存位置,所以让我们看看匹配的是什么。这将是倒数第二行:03 /r ADD r32, r/m32。我们回到指令摘要Table(没有 VEX 前缀的指令) 章节 3.1.1.1 操作码列,看看神奇的 /r 是什么:表示指令的ModR/M字节包含一个寄存器操作数和一个r/m操作数。

好的,所以图2-1。 Intel 64 和 IA-32 架构指令格式 向我们展示了指令的外观。到目前为止,我们知道我们不会有任何前缀,操作码将为 03 并且我们将至少使用 modr/m 字节。那么让我们来看看如何解决这个问题。看Table 2-2。具有 ModR/M 字节 的 32 位寻址形式。列代表寄存器操作数,行代表内存操作数。由于我们的寄存器是 EDX,我们使用第 3 列。

内存操作数是[EBX+ECX*4+15h],可以使用8位或32位位移进行编码。为了获得更短的代码,我们将使用 8 位版本,因此行 [--][--]+disp8 适用。这意味着我们的 modr/m 字节将是 54.

我们也需要一个 SIB 字节。这些列在 Table 2-3 中。具有 SIB 字节 的 32 位寻址形式。由于我们的基础是 EBX,我们使用第 4 列和 [ECX*4] 的行,它为我们提供了 8B.

的 SIB 字节

最后我们添加我们的 8 位位移字节,即 15。因此,完整的指令是 03 54 8B 15。我们可以用汇编程序验证这一点:

2 00000000 03548B15                add edx, [ebx+ecx*4+15h]

您正在查看一个操作码映射,它在该字节匹配的指令模式中转换操作码的第一个字节。如果你想知道指令的字节数rest,你需要看看别处。

如果您查看 ADD 指令的页面,它会显示如下内容:

00 /r        ADD r/m8, r8

这告诉您 00 字节后跟一个 ModR/M 字节,该字节在寄存器字段中包含寄存器 r 并且该寄存器是一个 8 位寄存器,即ADD 指令的第二个操作数(指令模式中的 r8),而第一个操作数在 ModR/M 字节

的其余部分

现在,如果您查看 ModR/M 字节的文档,它会告诉您一个 ModR/M 字节有 3 个字段——一个 2 位的 'mod' 字段,一个3 位 'register/opcode' 字段和一个 3 位 'r/m' 字段。然后它会给出所有 256 个 ModR/M 字节值的 table,并注明这些字段在每种情况下的含义。 table(通常)组织为 8 列的 32 行——32 行分为 4 组,每组 8 组,组对应于 'mod' 字段位和组内的行'r/m' 字段位,而列对应于 'register/opcode' 字段位。它有点奇怪,因为 'mod' 是前 2 位,'r/m' 是后 3 位,中间是 'register/opcode',但它是有意义的 'mod'和 'r/m' 位紧密相关并一起描述一个操作数,而 'register/opcode' 位几乎完全独立,描述另一个操作数或作为操作码的一部分。

Instruction Prefix                0 or 1 Byte
Address-Size Prefix               0 or 1 Byte
Operand-Size Prefix               0 or 1 Byte
Segment Prefix                    0 or 1 Byte
Opcode                            1 or 2 Byte
Mod R/M                           0 or 1 Byte
SIB, Scale Index Base (386+)      0 or 1 Byte
Displacement                      0, 1, 2 or 4 Byte (4 only 386+)
Immediate                         0, 1, 2 or 4 Byte (4 only 386+)

Format of Postbyte(Mod R/M from Intel-Doku)
------------------------------------------
MM RRR MMM

MM  - Memory addressing mode
RRR - Register operand address
MMM - Memory operand address

RRR Register Names
Filds  8bit  16bit  32bit
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

---

16bit memory (No 32 bit memory address prefix)
MMM   Default MM Field
Field Sreg     00        01          10             11=MMM is reg
000   DS       [BX+SI]   [BX+SI+o8]  [BX+SI+o16]
001   DS       [BX+DI]   [BX+DI+o8]  [BX+DI+o16]
010   SS       [BP+SI]   [BP+SI+o8]  [BP+SI+o16]
011   SS       [BP+DI]   [BP+DI+o8]  [BP+DI+o16]
100   DS       [SI]      [SI+o8]     [SI+o16]
101   DS       [DI]      [DI+o8]     [SI+o16]
110   SS       [o16]     [BP+o8]     [BP+o16]
111   DS       [BX]      [BX+o8]     [BX+o16]
Note: MMM=110,MM=0 Default Sreg is DS !!!!

32bit memory (Has 67h 32 bit memory address prefix)
MMM   Default MM Field
Field Sreg     00        01          10             11=MMM is reg
000   DS       [EAX]     [EAX+o8]    [EAX+o32]
001   DS       [ECX]     [ECX+o8]    [ECX+o32]
010   DS       [EDX]     [EDX+o8]    [EDX+o32]
011   DS       [EBX]     [EBX+o8]    [EBX+o32]
100   SIB      [SIB]     [SIB+o8]    [SIB+o32]
101   SS       [o32]     [EBP+o8]    [EBP+o32]
110   DS       [ESI]     [ESI+o8]    [ESI+o32]
111   DS       [EDI]     [EDI+o8]    [EDI+o32]
Note: MMM=110,MM=0 Default Sreg is DS !!!!

---

SIB is (Scale/Base/Index)
SS BBB III
Note: SIB address calculated as:
<sib address>=<Base>+<Index>*(2^(Scale))

Fild   Default Base
BBB    Sreg    Register   Note
000    DS      EAX
001    DS      ECX
010    DS      EDX
011    DS      EBX
100    SS      ESP
101    DS      o32        if MM=00 (Postbyte)
SS      EBP        if MM<>00 (Postbyte)
110    SS      ESI
111    DS      EDI

Fild  Index
III   register   Note
000   EAX
001   ECX
010   EDX
011   EBX
100              never Index SS can be 00
101   EBP
110   ESI
111   EDI

Fild Scale coefficient
SS   =2^(SS)
00   1
01   2
10   4
11   8