我正在努力学习如何编写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 。
我究竟做错了什么?
I'm trying to learn how to write gcc inline assembly.
The following code is supposed to perform an shl instruction and return the result.
#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; }Compilation fails with error: impossible constraint in asm
The problem is basically with "i"(b). I've tried "o", "n", "m" among others but it still doesn't work. Either its this error or operand size mismatch.
What am I doing wrong?
最满意答案
如上所述,您的代码正确编译(我已启用优化)。 但是,我相信你可能会发现这有点好一些:
#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
As written, you code compiles correctly for me (I have optimization enabled). However, I believe you may find this to be a bit better:
#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; }Note that the 'J' is for 64bit. If you are using 32bit, 'I' is the correct value.
Other things of note:
You are truncating your rotate value from uint64_t to int? Are you compiling for 32bit code? I don't believe shl can do 64bit rotates when compiled as 32bit. Allowing 'c' on the input constraint means you can use variable rotate amounts (ie not hard-coded at compile time). Since shl modifies the flags, use "cc" to let the compiler know. Using the [name] form makes the asm easier to read (IMO). The %b is a modifier. See https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#i386OperandmodifiersIf you want to really get smart about inline asm, check out the latest gcc docs: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
更多推荐
发布评论