如何让MIPS平台GCC在返回前立即恢复栈指针?
MIPS GCC叶子函数栈指针恢复与返回指令间指令的问题解决办法
当GCC编译MIPS架构的叶子函数时,可能生成这类汇编代码:
addiu $sp, $sp, 72 sb $v1, 0($v0) lbu $a0, 5($t2) lw $v0, 0($t1) sb $a0,1($v0) lbu $v1,6($t2) lw $v0,0($t1) sb $v1,2($v0) lw $a0,0($t1) lbu $v0,7($t2) jr $ra sb $v0,3($a0)
这里addiu $sp, $sp, 72是栈指针恢复指令,但它和返回指令jr $ra之间有大量指令。在抢占式操作系统中,若线程在这两条指令间被硬件中断打断,中断结束后调度高优先级线程会破坏原线程的栈,该问题仅存在于叶子函数中。
针对这个问题,MIPS GCC提供了几个编译选项来规避:
-mno-delayed-branch:禁用延迟分支优化,让jr $ra的延迟槽不再填充指令,栈指针恢复指令会紧邻返回指令执行。代价是全局关闭延迟分支优化,会有一定性能损耗。-mno-shared:如果编译静态链接程序,该选项会让编译器生成更保守的栈操作代码,避免栈指针恢复后安排过多指令再返回。- 函数级属性控制:对特定叶子函数使用
__attribute__((optimize("-mno-delayed-branch"))),仅针对该函数禁用延迟分支,避免全局性能影响。
如果只是调试场景,也可以用-O0关闭所有优化,但会大幅降低程序运行效率,不建议生产环境使用。
内容的提问来源于stack exchange,提问作者yuwen
相关产品推荐
相关产品推荐

