ARM64汇编str指令触发SIGBUS错误的原因及排查方法
错误根因
这个SIGBUS是栈对齐违规触发的硬件异常,核心逻辑如下:
- ARM64架构的过程调用标准(AAPCS64)强制要求:栈指针
sp必须始终保持16字节对齐,不管是函数刚入口的时候,还是后续用sp做基址访问栈内存的时候,都不能破坏这个对齐规则。 - 你进入
asmQuickSort函数的时候,sp本来是对齐的——因为C++调用方在执行BL跳转前已经把栈调整到16字节对齐状态,BL指令只修改lr寄存器不动sp。但你第3行写了sub sp, sp, #8,直接把sp减了8,这下sp的地址就变成8字节偏移,彻底打破了16字节对齐要求。 - 第4行
str w1, [sp]是用sp做基址访存,ARM64实板默认开启了严格的栈对齐检查,只要sp不满足16字节对齐,哪怕你访问的是4字节、1字节的数据,都会直接触发对齐异常,内核就会向进程发送SIGBUS信号。 - qemu-aarch64的用户态模拟默认没开启这么严格的硬件检查,会默默兼容非对齐的sp访存,所以qemu跑的时候没报错,这也是这类问题特别容易踩坑的点:模拟环境和实板行为不一致。
注:很多人误以为访存只要和数据宽度对齐就行,比如存4字节的w寄存器只要地址是4的倍数就没问题,这个规则对x0-x28这些通用寄存器当基址的场景成立,但只要基址是sp,硬件就强制要求sp本身必须16字节对齐,和访问的数据长度没有关系。
排查&修复方向
- 先做最小验证:把第3行的
sub sp, sp, #8改成sub sp, sp, #16,对应的第5行栈回收指令改成add sp, sp, #16,重新编译上板运行,如果SIGBUS直接消失,就能100%确认是栈对齐问题。 - 全量检查所有手写汇编代码的栈操作:所有调整sp分配栈空间的指令,偏移量必须是16的整数倍,哪怕你只需要存1个4字节的寄存器,也要凑够16字节的栈分配,不能只分配8字节、4字节。
- 检查编译配置:确认没有用特殊选项关闭栈对齐要求,交叉编译工具链是否为标准aarch64工具链,有没有错误混入32位ARM的编译参数。
- 如果后续在汇编函数里要调用其他C函数,一定要在执行bl指令前再次确认sp是16字节对齐的,不然哪怕你自己的代码不访问栈,被调用函数只要一碰栈也会触发同样的错误。
额外提一句你当前汇编代码的逻辑问题:函数入参x0是数组首地址、x1是元素个数7,你上来第一行把x2改成x1-1,第二行直接把x1改成0,两个入参都被覆写了,后续真实现快排逻辑的时候记得先把需要复用的入参保存到栈上再修改。
内容的提问来源于stack exchange,提问作者gongkaibo
相关产品推荐
相关产品推荐

