8位旋转的内联装配尺寸不匹配

时间:2017-12-27 20:20:50

标签: c x86 inline-assembly att

我正在尝试使用内联汇编在C中编写左旋转操作,如下所示:

byte rotate_left(byte a) {
    __asm__("rol %0, $1": "=a" (a) : "a" (a));
    return a;
}

(其中字节的typedefed为unsigned char)。

这会引发错误

  

/tmp/ccKYcEHR.s:363:错误:`rol'的操作数大小不匹配。

这里有什么问题?

1 个答案:

答案 0 :(得分:3)

AT& T语法使用与Intel语法相反的顺序。旋转计数必须是第一个,而不是最后一个:rol $1, %0

此外,您不需要也不应该使用内联asm:https://gcc.gnu.org/wiki/DontUseInlineAsm

Best practices for circular shift (rotate) operations in C++中所述,GNU C具有窄旋转的内在函数,因为旋转习语识别代码无法优化旋转计数的and。 x86移位/旋转使用count & 31掩盖计数,即使对于8位和16位,但旋转仍然环绕。尽管如此,它确实很重要。

无论如何,gcc有一个内置函数用于窄旋转以避免任何开销。在__rolb中有一个x86intrin.h包装器,但MSVC使用自己的__rotr8,依此类推intrin.h。无论如何,clang不支持旋转的__builtinx86intrin.h包装器,但是gcc和ICC都支持。

#include <stdint.h>
uint8_t rotate_left_byte_by1(uint8_t a) {
    return __builtin_ia32_rolqi(a, 1);  // qi = quarter-integer
}

我使用了来自uint8_t的{​​{1}},而不是正常人,而不是定义stdint.h类型。

这根本不用clang编译,而是it compiles as you'd hope with gcc7.2

byte

这为你提供了一个函数,它可以像你的内联编译一样有效,但它可以完全优化编译时常量,并且编译器知道它是如何工作的/它做了什么,并且可以相应地进行优化。