【问题标题】:How do I tell GCC asm that an input register is clobbered?我如何告诉 GCC asm 输入寄存器被破坏了?
【发布时间】:2014-11-15 03:05:34
【问题描述】:

我正在尝试通过 x86 mul 指令执行 64=32x32 乘法,但我只需要结果的高位双字(edx 寄存器)。所以很自然地,我尝试将edx 列为输出寄存器,将eax 列为被破坏的寄存器。

这对我来说似乎很自然,但eax 也是一个输入寄存器。当我试图告诉 GCC eax 已被破坏时,它会给出一条错误消息。

__asm__("mull\t%2" : "=d"(div10) : "%a"(UINT32_C(0x1999999A)), "r"(number)
    : "cc", "rax");

如果我尝试这样做,它会抛出以下错误消息:

divmod10.cpp:76:91: error: can’t find a register in class ‘AREG’ while reloading
‘asm’
divmod10.cpp:76:91: error: ‘asm’ operand has impossible constraints

省略它会编译,但会破坏代码。 GCC 最终依赖于 eax 未被破坏,这是不正确的:

        movl    $429496730, %eax
#APP
# 76 "divmod10.cpp" 1
        mull    %esi
# 0 "" 2
#NO_APP
        movl    %edx, %esi
#APP
# 78 "divmod10.cpp" 1
        mull    %edx
# 0 "" 2
#NO_APP

我该如何做我想做的事?

【问题讨论】:

  • 来自文档 (gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html):It is not possible to use Clobbers to inform the compiler that the values in these inputs are changing. 使用垃圾变量作为输出:__asm__("mull\t%2" : "=d"(div10), "=a"(junk) : "1"(UINT32_C(0x1999999A)), "r"(number) : "cc");

标签: c gcc x86 inline-assembly


【解决方案1】:

只需为输出设置一个无用的温度,编译器就会对其进行优化。例如:

__asm__("mull\t%2" : "=d"(div10), "=a"((int){0})
    : "a"(UINT32_C(0x1999999A)), "r"(number) : "cc");

这是我所知道的处理破坏输入的最简单方法。

【讨论】:

    猜你喜欢
    • 2013-07-04
    • 2017-01-02
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2014-12-21
    相关资源
    最近更新 更多