在全局范围内,代码只有在ASM语句本身内部发生跳转时才会运行.C语言中的执行路径无法进入和离开asm
语句,因此编译器没有地方放置设置输入操作数或将输出操作数存储到相关C变量的代码.如果您希望发生这种情况,请使用you have to write code for it yourself, exactly like writing a function in a separate 101 file.(在全局作用域ASM语句中使用.text
,以防编译器留下当前部分的其他内容.)
例如sd sp, user_stack_pointer
作为伪指令,或者auipc
具有地址的%hi
部分并使用%lo(user_stack_pointer)
作为存储指令中的偏移量.看看编译器生成的ASM,看看它是如何访问全局vars(https://godbolt.org/)的;我只是从内存出发,这可能不太适合RV64;我可能还记得MIPS.
或者,如果您想让编译器为您执行.global
和标签,请使用__attribute__((naked))
.您仍然需要用基本的asm
语句(没有操作数)编写整个函数体;it's not officially supported to use Extended 103 (with operands) in naked functions:https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html--但它最多只是一个警告,而不是编译时错误,所以编译器不会阻止您依赖碰巧工作代码.
此外,编译器不会在naked
函数的末尾发出ret
,因此无论如何都不能让执行出现在ASM语句的底部,从而使输出操作数变得毫无用处.你得跑到ret
英里或者跳到某个地方.
如果执行跳到中间之后从ASM语句的底部出来(例如,像这个异常处理程序,而不是从C __asm__
语句本身开始执行),无论它在哪里,甚至在函数内部,实际上都是未定义的行为.作为the GCC manual documents、asm statements may not perform jumps into other asm statements, only to the listed GotoLabels. GCC’s optimizers do not know about other jumps; therefore they cannot take account of them when deciding how to optimize.
如果这真的奏效,那你就走运了."=r"(global_var)
操作数的代码可能依赖于一些寄存器,这些寄存器是由编译器放在asm
语句前面的指令设置的,如果您跳到asm
语句的中间,这些指令就不会执行.