ARM C代码内嵌汇编跳转函数被优化无法执行如何解决
问题根源
- 编译器默认不会识别内嵌汇编的副作用:ARMCC在优化开启时,会自动删除没有可见副作用的函数调用。你的
jump函数没有返回值、没有修改全局变量或入参,编译器看不到汇编块内的跳转逻辑,就判定这个函数调用没有任何作用,不仅把jump函数本身优化成了直接返回(BX lr),还直接删除了main里的jump()调用,甚至把后面没用的变量赋值逻辑也全部优化掉了。 volatile修饰函数属于无效用法:C标准里volatile只能用于修饰数据对象,修饰函数返回值不会被编译器识别,自然起不到防止优化的作用。
解决方法
- 给内嵌汇编添加
__volatile限定:这是ARM系列编译器针对内嵌汇编的标准语法,显式告诉编译器该汇编块存在不可预测的副作用,不能被优化删除、也不能和其他指令重排。修改后的代码示例:
void jump(void) { __asm __volatile { B 0x15000 } // 可选:添加__builtin_unreachable()告知编译器汇编后的代码永远不会执行,消除冗余警告 __builtin_unreachable(); }
- 给函数添加专用属性:搭配
__attribute__((noreturn, noinline))修饰jump函数,noreturn告诉编译器该函数不会返回,不需要处理调用后的返回逻辑;noinline防止编译器把函数内联到调用位置,适配需要单独调用的场景:
__attribute__((noreturn, noinline)) void jump(void) { __asm __volatile { LDR PC, =0x15000 } __builtin_unreachable(); }
补充说明:推荐用
LDR PC, =0x15000代替B 0x15000,B指令的跳转范围有限(ARM模式下最大±32MB,Thumb模式更小),超出范围会编译报错,直接给PC寄存器赋值可以实现全32位地址空间跳转,兼容性更好。
内容的提问来源于stack exchange,提问作者TJ1
相关产品推荐
相关产品推荐

