gcc内联汇编时出错

时间:2014-10-12 20:11:19

标签: c gcc assembly x86 x86-64

我正在尝试学习如何编写gcc内联汇编。

以下代码应执行shl指令并返回结果。

#include <stdio.h>
#include <inttypes.h>

uint64_t rotate(uint64_t x, int b)
{
    int left = x;
    __asm__ ("shl %1, %0"
             :"=r"(left)
             :"i"(b), "0"(left));

   return left;
}

int main()
{
    uint64_t a = 1000000000;
    uint64_t res = rotate(a, 10);
    printf("%llu\n", res);
    return 0;
}

编译因error: impossible constraint in asm

而失败

问题基本上是"i"(b)。我已经尝试了"o""n""m"等等,但它仍然不起作用。要么出现此错误,要么operand size mismatch

我做错了什么?

1 个答案:

答案 0 :(得分:4)

如上所述,您的代码正确编译(我已启用优化)。但是,我相信您可能会发现这更好一点:

#include <stdio.h>
#include <inttypes.h>

uint64_t rotate(uint64_t x, int b)
{
    __asm__ ("shl %b[shift], %[value]"
             : [value] "+r"(x)
             : [shift] "Jc"(b)
             : "cc");

   return x;
}

int main(int argc, char *argv[])
{
    uint64_t a = 1000000000;
    uint64_t res = rotate(a, 10);
    printf("%llu\n", res);
    return 0;
}

请注意,'J'代表64位。如果您使用32位,“我”是正确的值。

其他注意事项:

  • 您是否将旋转值从uint64_t截断为int?你在编译32位代码吗?我不相信当编译为32位时,shl可以进行64位旋转。
  • 在输入约束上允许'c'意味着您可以使用可变旋转量(即在编译时不进行硬编码)。
  • 由于shl修改了标志,使用“cc”让编译器知道。
  • 使用[name]表单使asm更易于阅读(IMO)。
  • %b是修饰符。请参阅https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#i386Operandmodifiers

如果您想真正了解内联asm,请查看最新的gcc文档:https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html