assembly 在函数外使用内联asm时无法指定操作数

kjthegm6  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(94)

我的代码

unsigned long user_stack_pointer;

__asm__(
    ".global exception_handling_entry\n"
    "exception_handling_entry:\n"
    "add %0, sp, x0\n"
    : "=r" (user_stack_pointer)
);

字符串
gcc在使用riscv64-unknown-elf-gcc test.c -o test时显示错误')' before ':' token

unsigned long user_stack_pointer;

int main() {
    __asm__(
    ".global exception_handling_entry\n"
    "exception_handling_entry:\n"
    "addi %0, sp, 0\n"
    : "=r" (user_stack_pointer)
    );

    return 0;
}


这让我很困惑。
我找不到一个好的解决办法。

6qftjkof

6qftjkof1#

在全局范围内,只有在asm语句本身内部发生跳转时,代码才会运行。在C术语中,执行路径无法进入和离开asm语句,因此编译器无法放置设置输入操作数或将输出操作数存储到相关C变量的代码。如果你想这样做,你必须自己编写代码,就像在一个单独的.s文件中编写一个函数一样。(在全局范围的asm语句中使用.text,以防编译器在当前部分留下其他内容。)
例如,sd sp, user_stack_pointer作为伪指令,或者auipc使用地址的%hi部分,并使用%lo(user_stack_pointer)作为存储指令中的偏移量。查看编译器生成的asm,看看它如何访问全局变量(https://godbolt.org/);我只是从内存开始,这可能不适合RV 64;我可能记住了MIPS。
或者,如果你想让编译器为你做.global和标签,使用__attribute__((naked))。(无操作数);官方不支持使用扩展asm(带操作数)在裸函数中https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html-但它最多只是一个警告,而不是编译时错误,因此编译器不会阻止您依赖happens-to-work代码。
此外,编译器不会在naked函数的末尾发出ret,所以无论如何不能让执行从asm语句的底部出来,使输出操作数无用。您需要ret或跳转到某个地方。
如果执行从asm语句的底部跳到中间,(例如,像这个异常处理程序,而不是从C __asm__语句本身开始执行),无论它在哪里,甚至在函数内部。作为the GCC manual documentsasm语句可能不会执行跳转到其他asm语句,GCC的优化器不知道其他跳转;因此在决定如何优化时无法考虑它们。
"=r"(global_var)操作数的代码可以依赖于编译器在asm语句之前设置的一些寄存器,如果你跳到它的中间,这些寄存器就不会执行。

相关问题