错误的寄存器'%rbx'与'l'后缀一起使用

时间:2013-01-05 12:50:24

标签: c linux gcc assembly inline-assembly

我正在尝试使用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

这里有什么问题?

3 个答案:

答案 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的发布历史记录)。