可以从英特尔开发人员手册中的标准操作码映射中推断出哪个操作数“拥有” ModR/M 字节中的 REG 部分,以及哪个操作数具有 Mod+RM 部分(可选地带有方向位)?方向位是否符合所有具有两个操作数的运算(方向可以不明确)?
有关我所在位置的一些信息
我从一字节操作码映射的顶部开始。这里我们有:
0 1 2 3 4 5 6 7
+--------|--------|--------|--------|--------|---------|---------|---------|
0 | ADD | PUSH | POP |
| Eb, Gb | Ev, Gv | Gb, Eb | Gv, Ev | AL, Ib | rAX, Iz | ES(i64) | ES(i64) |
+--------|--------|--------|--------|--------|---------|---------|---------|
1 | ADC
…
我将ADD
视为操作码00h
和02h
。
字母说明:
Addressing methods:
…
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 scaling factor, a displacement.
G The reg field of the ModR/M byte selects a general register.
Example: AX (000)
…
-------------------------------------------------------------------------
Operand types:
…
b Byte, regardless of operand-size attribute.
v Word, doubleword or quadword (in 64-bit mode), depending on
operand-size attribute.
…
如上所述,我正在查看ADD
操作码00h
和02h
。此外,我只考虑 32 位(目前)。操作说明表为:
Opcode Instruction Op/en Description
00 /r ADD r/m8,r8 MR Add r8 to r/m8.
02 /r ADD r8,r/m8 RM Add r/m8 to r8.
一些测试用例:
00 05 e25a4600 add [0x465ae2], al
00 0d e25a4600 add [0x465ae2], cl
00 06 add [esi], al ; Eb, Gb
02 06 add al, [esi] ; Gb, Eb
00 c8 add al, cl ; Eb, Gb
02 c8 add cl, al ; Gb, Eb
00 05 e0514600 add [0x4651e0], al
02 05 e0514600 add al, [0x4651e0]
ModR/M 字节:
7 6 5 4 3 2 1 0 Bit
+------------+------------------+------------------+
| MOD | REG/Opcode | R/M |
+------------+------------------+------------------+
来自二进制测试用例的操作码和 ModR/M:
Opcode Mod REG/opc R/M
0000 0000 00 000 101 add [0xNNNNNN], al
0000 0000 00 001 101 add [0xNNNNNN], cl
0000 0000 00 000 110 add [esi], al
0000 0010 00 000 110 add al, [esi]
0000 0000 11 001 000 add al, cl
0000 0010 11 001 000 add cl, al
0000 0000 00 000 101 add [0xNNNNNN], al
0000 0010 00 000 101 add al, [0xNNNNNN]
|
+-----> Direction bit?
问题部分:
(Ups,这个介绍越来越多,TLDR?)但是,最后:
- 操作码映射(第一个表)中对
E
的描述指出,“操作码后面有一个 ModR/M 字节并指定操作数。操作数可以是通用寄存器或内存地址。”
所以我的问题是:什么定义了它是寄存器还是内存地址?就像这样:您一个接一个地读取字节。操作码具有E
表示法。- 是否基于操作码的方向位?
- 可以从第二个操作数中扣除吗? – 如:在这个具体示例中,第二个操作数具有
G
标志,该标志表示“ModR/M 字节的 reg 字段选择通用寄存器”。这永远都是真的吗? - 这会覆盖方向位吗?
- 是否基于操作码的方向位?
附录 B 有一个简短的部分说明:
B.1.4.8 Direction (d) Bit
In many two-operand instructions, a direction bit (d) indicates which operand is considered the source and which is the destination. See Table B-11.
Table B-11. Encoding of Operation Direction (d) Bit
+---+-----------------------------+---------------------------------+
| d | Source | Destination |
+---+-----------------------------+---------------------------------+
| 0 | reg Field | ModR/M or SIB byte |
| 1 | ModR/M or SIB Byte | reg Field |
+---+-----------------------------+---------------------------------x
2.这里的许多是什么意思?它在哪里定义哪些适用,哪些不适用?
希望这不会变得太长。
最佳答案
参见this Mod/RM 编码表。
首先,并不总是有方向位。据我所知,仅在 ALU ops* 中。方向位表示E部分或G部分中哪一个是源,哪一个是目的地。
定义 E 操作数是寄存器操作数还是内存操作数的是 Mod/RM 字节的 MOD 部分是 11(寄存器)还是不是(内存),正如您可能从我链接的表中看到的那样到。 R 字段并不总是对通用寄存器进行编码,它可以对其他类型的寄存器进行编码,甚至可以扩展操作码(两者也在该表中显示),但 G 字段始终对 GPR 进行编码(它指的是当然是 Mod/RM 字节,但是当它被称为 G 时,您知道它必须是 GPR,否则它可能是其他东西,这取决于它的操作数是什么指令)。
新指令都没有真正的方向位。它们中的大多数根本无法写入内存,除了仅写入而不读取/修改/写入的指令。例如,有 movaps r, r/m
和 movaps r/m, r
,以及 movdqa r, r/m
和 movdqa r/m、r
,它们可以被解释为具有方向位,但对于 movaps
来说,它是位 0,对于 movdqa
来说,它是位 4。您可能也可以说只有两种不同的编码。
*具体来说,由 00aa a0ds
描述的组,其中 aaa
是操作(add、adc、and、xor、or、sbb、sub、cmp,其中顺序从 0 到 7),d
是方向位,s
表示大小(0 表示字节操作,1 表示按当前模式和前缀区分的其他所有内容)
关于assembly - ModR/M字节中REG的所有者,方向位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17518507/