【问题标题】:Understanding Instruction Encoding?了解指令编码?
【发布时间】:2021-07-31 19:23:14
【问题描述】:

我用一个网站来编码这个:

movw $8, 4(%r8d,%esi,4)

得到:

encoding (hex): 67 66 41 C7 44 B0 04 08 00

多亏了你,我几乎明白了一切,除了 2 个小点:

  1. 这里我们将 2 字节立即移动到 4 字节地址。他们使用了 C7 操作码,根据我的表格,我的意思是以下之一:
  • 将 imm16 移动到 r/m16
  • 将 imm32 移动到 r/m32
  • mov imm32(符号扩展)到 r/m64

为什么没有匹配?

  1. 为什么立即数是 2 个字节?根据什么?

【问题讨论】:

    标签: assembly x86-64 att machine-code instruction-encoding


    【解决方案1】:

    有一个匹配。它是第一个“mov imm16 to r/m16”,因为在助记符movw 中有wr/m16 表示正在读取/写入 16 位(两个字节)的内存。碰巧您正在使用 32 位有效地址来识别要写入哪两个内存字节,但这不是 r/m16 表示法的一部分。

    立即数是两个字节,因为要写入两个字节。拥有更多是没有意义的。尽管有一些例子,比如第三种情况,立即数比操作数的大小短,并且是零或符号扩展的。

    【讨论】:

    • 但我不明白,我们正在对 32 位地址求和,所以我们得到 32 位地址... w 表示写入 16 位地址,所以我们采用较低的或较高的 16 位?
    • 我认为像“32 位地址”这样的术语会让你感到困惑。地址是 32 位,但我们用来识别 16 位的内存。例如,假设r8d + (esi * 4) + 4 等于0x12345678。然后您的movw 指令会将08 写入地址0x12345678 的字节,并将00 写入地址0x12345679 的字节。写入两个字节 = 16 位。如果您使用movb,则只会写入0x12345678 处的字节。如果您使用movl,则将写入0x12345678..0x1234567b 的四个字节(分别使用值08 00 00 00)。
    • @coolmo:字面意思是用 16 位地址写入意味着写入从 0x5678 开始的字节(它总是低位)。在 64 位长模式下没有对此进行编码,尽管在 32 位保护模式下(有点,您在寻址模式中变得更加受限)。无论哪种方式,它都几乎没用。
    • 现在很清楚了,最后有一个操作码用于 mov imm32(符号扩展)到 r/m64 和另一个用于 mov imm64 到 r/m64 我怎么知道要使用哪个(我怎么可能知道指令是否签署扩展名)?
    • @coolmo:在汇编级别上,您并不真正关心符号扩展:您指定要写入的实际值。如果汇编器可以将其表示为符号扩展值,它将汇编它;否则选择不同的编码或抱怨。至于mov imm64 to r/m64,我想你错了:不存在这样的编码。有一条指向mov imm64 to r64(仅限注册)REX.W + B8 的指令。如果您指定不适合 32 位符号扩展的立即数,GNU 汇编器将自动选择此编码,或者您可以使用 movabsq 助记符强制它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 2019-04-26
    • 2017-07-11
    • 2014-02-17
    • 2016-04-26
    • 2018-03-05
    相关资源
    最近更新 更多