assembly 为什么%rbp和%rax对于movl是无效的操作数?

4ioopgfo  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(145)

我尝试使用__asm__%rbp的值放入%rax寄存器中,以便可以获得对堆栈帧的引用,该引用在创建外部变量时不会更改。
我使用下面的代码来做这件事:

int some_variadic_function(int n, ...)
{
    __asm__("movl %rax, %rbp");
    return 0;   
}

int main() {
    some_variadic_function(3, 1, 2, 3);
    return 0;
}

然而,当我尝试用clang编译它时,我得到以下错误:

using_rbp.c:4:13: error: invalid operand for instruction
    __asm__("movl %rax, %rbp");
            ^
<inline asm>:1:7: note: instantiated into assembly here
        movl %rax, %rbp
             ^~~~~
1 error generated.

这似乎意味着我不能把%rbp直接放到%rax中,是这样还是这段代码有其他问题?
作为参考,我在Mac上使用x86-64硬件。

ig9co6j1

ig9co6j11#

你犯了一大堆错误。让我们一个一个来:
1.在AT&T的x86汇编语法中,如果你在指令上提供了一个大小后缀,它必须与从操作数推断出的大小相匹配。大小后缀几乎总是不需要的x86(我能想到的唯一的情况是,当你直接将一个立即值移动到内存中时,需要它们):我建议不要使用它们,除非汇编程序抱怨它们的缺失。
1.在AT&T汇编语法中,目的地是 second;mov %rax, %rbp将RAX复制到RBP,而不是相反。
1.在GNU风格的内联汇编中,%开始一个转义序列(类似于printf);要写一个文字寄存器名,你必须将百分号加倍。这就是为什么你会从clang得到错误,而不是从汇编程序得到错误。

  1. GNU风格的内联汇编必须用“操作数约束”来注解,这样编译器才能理解你在做什么。你不能简单地将一个值移到RAX中并期望它成为返回值。请参阅https://gcc.gnu.org/onlinedocs/gcc-11.3.0/gcc/Using-Assembly-Language-with-C.html-- read all 这一手册部分,而不仅仅是我链接的摘要页面。
    1.在64位System V ABI for x86中,%rbp是一个普通的通用寄存器,而不是“帧指针”。
    正确的做法是
long some_variadic_function(int n, ...)
{
    long rv;
    __asm__("mov %%rbp, %0" : "=r" (rv));
    return rv;
}

但是,这必须使用-fno-omit-frame-pointer编译,否则返回值将是垃圾。
你可能正遭受着臭名昭著的XY problem的折磨。问一个关于你最初试图做的事情的新问题,而不是关于你试图解决问题的细节,我们可能会更有帮助。

相关问题