armv6-m裸机开发中如何修改gcc生成的中断异常处理函数返回地址
GCC 原生提供了修改函数返回地址的能力,无需自行编写汇编封装层,具体方案如下:
方案说明
1. 核心内置函数
使用GCC专属内置函数 __builtin_set_return_address(void *target_addr) 即可直接修改当前函数的返回地址,该函数对普通C函数、带__attribute__((interrupt("type")))属性的ARM异常处理函数均生效。
- 对于普通C函数:该函数会修改栈帧中存储的调用方返回地址,函数退出时会直接跳转到你指定的
target_addr,而非原调用位置。 - 对于ARM异常处理函数:GCC生成中断函数栈帧时,会将异常触发时保存的返回地址(对应异常触发时的LR寄存器值)存储在栈帧固定位置,
__builtin_set_return_address会自动适配中断函数的栈帧结构,修改该返回地址,异常退出时就会跳转到你设置的目标地址。
2. 异常场景注意事项
针对你提到的未定义指令等异常场景,需要注意两点:
- 你需要自行根据异常类型计算正确的目标地址:比如ARMv6-M架构下未定义指令异常的返回地址默认指向触发异常的指令本身,你需要根据指令长度(2字节Thumb指令或4字节Thumb-2指令)给目标地址加上对应偏移,避免重复触发异常。
- 调用该内置函数时尽量放在异常处理函数的顶层作用域,不要在嵌套代码块、内联函数内调用,避免栈帧结构变化导致修改位置错误。
3. 兼容性说明
该内置函数是GCC专属扩展,不依赖第三方组件,只要你的编译参数和目标架构匹配(比如指定-march=armv6-m -mthumb),就可以稳定使用,不需要自行处理寄存器保存、编译器优化适配的问题。
内容的提问来源于stack exchange,提问作者Poohl
相关产品推荐
相关产品推荐

