AArch64内核中值传递15字节结构体时串口输出异常问题
AArch64内核中值传递15字节结构体时串口输出异常问题
我现在在开发一个简单的AArch64内核,遇到了个挺奇怪的问题:当我按值传递一个15字节的结构体时,串口输出的内容和预期的0a1完全对不上;但只要把这个结构体的大小改成16字节,之前的异常就消失了,输出也正常了。
我的开发环境
- QEMU模拟器版本:9.0.2
- 编译器版本:aarch64-linux-gnu-g++ (Ubuntu 14.2.0-4ubuntu2) 14.2.0
相关代码片段(main.cpp)
extern "C" void _start() { asm volatile("ldr x11, =stack_top\n\t" // 剩余代码未完整给出
问题分析与排查建议
这个问题大概率和AArch64的**过程调用标准(PCS)**脱不了干系,我给你捋捋关键逻辑:
在AArch64的官方调用约定里,结构体按值传递时的处理规则是根据大小和对齐属性来定的:
- 要是结构体总大小≤8字节,直接用单个通用寄存器传递就行;
- 大小在9-16字节之间的话,会用两个通用寄存器拼接起来传递;
- 但这里最坑的点是对齐要求——15字节的结构体虽然没到16字节,但AArch64的调用约定可能会要求按16字节的对齐规格来处理传递,要是你的内核代码(比如串口输出函数)没考虑到这种“不完整寄存器传递”的情况,比如默认按16字节来读取参数,那第二个寄存器里的高1字节就是垃圾数据,自然会导致输出异常;而改成16字节后,刚好填满两个寄存器,传递逻辑和内存布局都符合预期,输出就正常了。
另外还有个可能的点:你手写的_start汇编里的栈设置有没有符合AArch64的对齐要求?AArch64明确规定,进入C函数前栈指针必须是16字节对齐的,要是栈没对齐,参数传递时的内存访问很容易出问题,进而影响串口输出的内容。
给你几个排查方向:
- 先检查串口输出函数处理这个结构体参数的逻辑——是不是默认按16字节来读取数据,没考虑到15字节的截断情况?
- 用
-S参数编译代码,看看15字节和16字节结构体在传递时的汇编差异,比如寄存器的使用、栈上临时存储的情况,对比一下就能发现问题; - 确认
_start里的栈设置有没有保证16字节对齐,比如stack_top的地址是不是16的倍数; - 给15字节的结构体加个对齐属性
__attribute__((aligned(16))),看看加上后输出是否正常——如果正常了,那基本就是对齐导致的传递逻辑差异。
备注:内容来源于stack exchange,提问作者Zone233
相关产品推荐
相关产品推荐

