我正在尝试使用内联汇编在C中编写左旋转操作,如下所示:
byte rotate_left(byte a) {
__asm__("rol %0, $1": "=a" (a) : "a" (a));
return a;
}
(其中字节的typedefed为unsigned char)。
这会引发错误
/tmp/ccKYcEHR.s:363:错误:`rol'的操作数大小不匹配。
这里有什么问题?
答案 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不支持旋转的__builtin
或x86intrin.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
这为你提供了一个函数,它可以像你的内联编译一样有效,但它可以完全优化编译时常量,并且编译器知道它是如何工作的/它做了什么,并且可以相应地进行优化。