我正在尝试使用gcc编译器在linux下编译此代码:
static inline unsigned long get_current(void)
{
unsigned long current;
asm volatile (
" movl %%esp, %%eax;"
" andl %1, %%eax;"
" movl (%%eax), %0;"
: "=r" (current)
: "i" (0xfffff000)
);
return current;
}
但是我收到了这个错误:
program.c: Assembler messages: program.c:455: Error: incorrect
register `%rbx' used with `l' suffix
这里有什么问题?
答案 0 :(得分:3)
虽然以上是正确的,但我认为它实际上不是正确的解决方案。如果你有64位操作系统,你应该使用64位操作来获得"获取当前"。
asm volatile (
" movq %1, %%rax
" andq %%rsp, %%rax;" // We only care about lower bits.
" movq (%%rax), %0;"
: "=r" (current)
: "i" (0xfffffffffffff000)
: "rax" // Remember to mark any temporary registers modified in "clobber"
);
我重新安排了说明,因为您无法在大多数说明中使用64位立即数。
答案 1 :(得分:2)
显然,你正在编译64位。如果它不是您想要的,请尝试使用gcc -m32,或使用64位寄存器(%esp在x64上完全没有意义)。
答案 2 :(得分:2)
我会这样编码:
static inline unsigned long get_current(void)
{
unsigned register long current asm("sp");
asm volatile ("" : "=r"(current));
return (current & ~ (unsigned long)0xfff);
}
这可以在64位和32位上编译;创建以下代码:
Disassembly of section .text: 0000000000000000 <get_current>: 0: 48 89 e0 mov %rsp,%rax 3: 48 25 00 f0 ff ff and $0xfffffffffffff000,%rax 9: c3 retq
分别为32位:
Disassembly of section .text: 00000000 <get_current>: 0: 89 e0 mov %esp,%eax 2: 25 00 f0 ff ff and $0xfffff000,%eax 7: c3 ret
gcc内联汇编程序的一个很好的东西是能够将变量绑定到寄存器,是的,如图所示,它在x86上识别sp
。
编辑: oops ...只是注意到gcc 3.4.5为上面创建了有趣的代码 - 即使在高优化级别,它通常会自行消除帧指针,上面的源代码将会make创建一个framepointer(用于函数的非静态实例化)。使用gcc 3.4.5上的-fomit-frame-pointer
进行显式编译或使用gcc 4.x创建现在显示的正确代码(请参阅gcc 3.4.5的发布历史记录)。