【问题标题】:Simple instruction encode简单指令编码
【发布时间】:2020-10-08 03:38:19
【问题描述】:

我们来看下面的汇编指令:

add    %cl,%bl

这被编码为:00cb,或0000000011001011二进制。将cb 放入 ModR/M 位域,如下所示:

  1   1   0   0   1   0  1   1
+---+---+---+---+---+---+---+---+
|  mod  |    reg    |    r/m    |
+---+---+---+---+---+---+---+---+

而且,旅馆查找 register field here 我们得到:

  • mod:11(寄存器寻址模式)
  • 注册:001(cl 注册)
  • r/m:011(bl 寄存器)

而且,我相信000000ds 是add 指令,而d=s=0 因为它们都是寄存器。这是对该指令如何编码的正确理解吗?此外,对于“完整编码”方案,以下是否准确(以字节而不是位为单位):

[empty]         0x0         0b11001011     [empty]        [empty]          [empty]
_ _ _ _        _ _             _              _           _ _ _ _          _ _ _ _
Prefix      Instruction    Mod-reg-r/m      Scale       displacement      immediate

在我尝试“解码”指令的过程中,我是否遗漏了什么?

【问题讨论】:

  • @PeterCordes 感谢您的反馈和链接。指令的编码方式非常简洁!
  • 哦,我误解了他们所说的“第二个操作数”是什么意思。他们并不意味着一个顺序,并且确实提到了 r/m,r 与 r, r/m 操作数顺序由不同的操作码选择。所以这个链接实际上很好。

标签: assembly x86 intel machine-code


【解决方案1】:

是的,看起来不错。

用于编码op r/m, r 与op r, r/m 以及8 位与16/32 位的通用模式(适用于可追溯到8086 的“传统”ALU 指令)确实使用操作码字节的低2 位以常规模式,但没有必要依赖它。

英特尔确实在其第 2 卷手册中完整记录了每条指令的每种编码的具体情况。例如,请参阅 add 的 Op/En 列和操作数编码表。 (另请参阅https://ref.x86asm.net/coder64.htm,它还指定了每个操作码的哪个操作数)。这些都让你知道哪些操作码需要 ModRM 字节,哪些不需要。

这些当然使用 Intel-syntax 命令。如果您尝试遵循手册和教程,同时使用 AT&T 语法(与 Intel 和 AMD 手册的操作数列表的顺序相反),您的生活会变得更加复杂。

例如00 /r 是listed 作为MR 操作数编码,从表中我们可以看到操作数1 = ModRM:r/m (r, w),所以它是读写的,并由r/m 字段编码。操作数 2 = ModRM:reg (r),因此它是由 reg 字段编码的只读源。

有趣的事实:00 00 是 add [rax], al,或 AT&T add %al, (%rax)

请注意,您可以让 GAS 选择任一编码:x86 XOR opcode differences

{load}  add    %cl,%bl        # 02 d9
{store} add    %cl,%bl        # 00 cb

另见Difference between MOV r/m8,r8 and MOV r8,r/m8

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 2014-02-17
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多