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

问题描述 投票:3回答:3

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

这有什么不对?

c linux gcc assembly inline-assembly
3个回答
2
投票

显然,你正在编译64位。如果它不是您想要的,请尝试使用gcc -m32,或者使用64位寄存器(%esp在x64上完全没有意义)。


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位立即数。


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&gt:
   0:   48 89 e0                mov    %rsp,%rax
   3:   48 25 00 f0 ff ff       and    $0xfffffffffffff000,%rax
   9:   c3                      retq

分别为32bit:

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为上面创建了有趣的代码 - 即使在高优化级别,它通常会自己消除帧指针,上面的源代码将创建一个framepointer(用于非静态)实例化功能)。在gcc 3.4.5上使用-fomit-frame-pointer进行显式编译或使用gcc 4.x创建现在显示的正确代码(请参阅gcc 3.4.5的发布历史记录)。

© www.soinside.com 2019 - 2024. All rights reserved.