assembly - ModR/M字节中REG的所有者,方向位

标签 assembly x86 disassembly opcode

可以从英特尔开发人员手册中的标准操作码映射中推断出哪个操作数“拥有” 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视为操作码00h02h

字母说明:

  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操作码00h02h。此外,我只考虑 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?)但是,最后:

  1. 操作码映射(第一个表)中对 E 的描述指出,“操作码后面有一个 ModR/M 字节并指定操作数。操作数可以是通用寄存器或内存地址。”

    所以我的问题是:什么定义了它是寄存器还是内存地址?就像这样:您一个接一个地读取字节。操作码具有 E 表示法。
    1. 是否基于操作码的方向位?
    2. 可以从第二个操作数中扣除吗? – 如:在这个具体示例中,第二个操作数具有 G 标志,该标志表示“ModR/M 字节的 reg 字段选择通用寄存器”。这永远都是真的吗?
    3. 这会覆盖方向位吗?

附录 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/mmovaps r/m, r,以及 movdqa r, r/mmovdqa 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/

相关文章:

c++ - 导入二进制文件gnu-assembler时检查标签之间的距离

windows - 使用 NASM 进行 Windows x64 汇编编程中未解析的外部符号 printf

c - 为什么清除中断标志会导致 C 中的段错误?

microcontroller - Atmel AVR 反汇编程序

Linux NASM 检测 EOF

c - 重新编译 -fPIC 问题

assembly - 用 LEA 指令减去寄存器?

x86 - 三重故障不会使系统复位

assembly - 获取组装说明的大小

c++ - 返回引用时,gcc 将 0x30 添加到 %eax