【问题标题】:Error: operand size mismatch for `movq'错误:“movq”的操作数大小不匹配
【发布时间】:2017-02-23 05:39:23
【问题描述】:

我正在尝试编译以下程序集...

movq $0x3534373536383235, 0x000000000055638f8
movq $0x55638f8, %rdi
retq

第一行抛出错误Error: operand size mismatch for 'movq'

这对我来说没有意义,因为它们都是 8 字节数字。

我做了一些研究,并推荐了movabsq,就像这样......

movabsq $0x3534373536383235, 0x000000000055638f8
movq $0x55638f8, %rdi
retq

但这会引发错误:Error: operand size mismatch for 'movabs'

我错过了什么?

这是我的 mac 的全部错误

level3.s:1:27: error: invalid operand for instruction
movq $0x3534373536383235, 0x000000000055638f8
                          ^~~~~~~~~~~~~~~~~~~

【问题讨论】:

标签: assembly x86-64


【解决方案1】:

如果您在引理MOV 下查看手册(诚然,这有点吓人),您会发现没有mov r/m64, imm64

有一种方法可以将完整的 64 位常量加载到寄存器中,也有一种方法可以将符号扩展的 32 位常量加载到 64 位内存位置,但是没有一条指令可以将 64 位立即数写入内存.

因此,您必须分两步完成,例如使用临时寄存器或分别将两个双字直接写入内存。

【讨论】:

    【解决方案2】:

    一种方法是:

    movabsq  $0x3534373536383235, %rax
    movabsq  %rax, 0x000000000055638f8
    

    正如另一条评论所说,您不能将 64 位立即数移动到 64 位内存地址,因为没有指令允许您这样做。缺少此操作码是因为操作码当前不能超过 15 个字节,并且两个 64 位值单独是 16 个字节,并且必须是操作码的一部分。此限制适用于较小的操作码,这些操作码也会因前缀而变得太大。因为您要移动到一个绝对 64 位的内存地址,所以您需要使用 movabs 或 movabsq,无论您的汇编程序喜欢哪个。

    【讨论】:

    • OP 同时指定了 64 位地址和 64 位常量。
    • 你知道为什么操作码不能超过 15 个字节吗?
    • @jeteon:整个指令被限制为15个字节;操作码最多为 2 个字节,如果包含强制前缀则更多。这个限制使设计快速解码器更容易。最初的 8086 一次解码一个字节或其他东西,但后来的 CPU 一次解码整个指令。确保一个固定宽度的缓冲区总是可以容纳一条完整的指令是有帮助的。 IDK 为什么他们选择 15 而不是 16 什么的,但是 4 位计数器可以容纳 15 而不是 16。
    • @PeterCordes : 8086 可以预取 6 个字节。
    • @MichaelPetch:是的,但它不是一次解码一个吗?或者那只是前缀?当然,16 位机器码获得这么大的唯一方法是通过前缀,所以一旦它通过前缀和操作码字节完成咀嚼,6 字节缓冲区(或 8088 中的 4 个?)(几乎)足够大持有操作数。现代 CPU 当然会并行解码多条指令组,因此长度上限显然很有用;如果 16 字节解码块(从下一个未解码指令的开头开始)不能包含整个指令,则不需要后备。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2018-02-11
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    相关资源
    最近更新 更多