我的代码
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;
}
型
这让我很困惑。
我找不到一个好的解决办法。
1条答案
按热度按时间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 documents,asm语句可能不会执行跳转到其他asm语句,GCC的优化器不知道其他跳转;因此在决定如何优化时无法考虑它们。"=r"(global_var)
操作数的代码可以依赖于编译器在asm
语句之前设置的一些寄存器,如果你跳到它的中间,这些寄存器就不会执行。