You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust嵌入式ARM Thumb目标下asm!宏如何获取SP寄存器的准确值

问题1解决方案

你可以给SVCall函数添加Rust原生的#[naked]属性,标记为裸函数:

  • 被该属性标记的函数,编译器不会自动生成任何函数入口(prologue)、出口(epilogue)代码,包括你遇到的sub sp, #8栈空间分配指令、寄存器自动压栈出栈逻辑都不会插入,所有栈操作和寄存器管理完全由你自己在asm!块中控制,你可以直接读取到异常触发后未经修改的原始sp值。
  • 注意裸函数内部只能包含asm!块,不能写普通Rust逻辑,你需要自己手动处理寄存器保存、后续defmt调用的参数传递、异常返回的寄存器恢复逻辑。

如果不想改写成全汇编的裸函数,也可以把SVC号提取逻辑单独抽成一个裸函数辅助接口,在普通异常处理函数的最开头调用,避免编译器插入的栈操作影响偏移计算。

问题2解答

不能默认sp会始终拷贝到r7寄存器:

  • 用r7作为帧指针是Thumb架构下开启帧指针编译选项时的默认行为,但该行为完全受编译器优化策略控制:如果开启了帧指针省略(-fomit-frame-pointer,高优化等级下很可能默认开启)、或者编译器版本、编译配置变动,都可能导致r7不再用作帧指针,硬编码依赖r7的代码会直接出现不可预期的错误,完全不具备可移植性和稳定性。

额外优化建议

你当前硬编码栈偏移的方式本身也和异常触发时的栈上下文强绑定,更稳定的实现是在裸函数中直接基于Cortex-M异常的硬件压栈规则计算:Cortex-M触发SVC异常时,硬件会自动按顺序压入R0、R1、R2、R3、R12、LR、PC、xPSR共8个寄存器,合计32字节,你拿到异常入口的原始sp后,直接加24(0x18)就能得到PC的存储地址,不需要依赖任何编译器生成的栈布局。


内容的提问来源于stack exchange,提问作者laptou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 20:06:05