ARM32 GCC环境下unsigned long long栈传参8字节对齐异常排查
问题原因分析
1. 未遵循Cortex-R52的AAPCS调用约定
你使用的gcc-arm-none-eabi-9-2020-q2-update针对Cortex-R52(ARMv8-R架构)遵循AAPCS64/ARMv8-R调用约定,对于可变参数函数的64位整数参数(如unsigned long long):
- 当启用硬浮点ABI(
-mfloat-abi=hard)时,前几个64位参数会优先使用通用寄存器对(如R0+R1)传递,而非直接压栈。 - 若
_printf中对va_list的处理(如va_start/va_arg)未适配AAPCS规则,会错误跳过寄存器中的参数,直接去栈上查找,导致va_list指向的地址不包含目标参数。 - 另外,若
_printf的函数声明未正确使用可变参数语法(如_printf(const char* fmt, ...)),GCC会按普通函数调用约定处理参数,进一步加剧传参位置混乱。
2. 小端字节序处理错误
Cortex-R52默认采用小端字节序,unsigned long long类型的0x123456789abcdef0在内存中存储顺序为:0xf0 0xde 0xbc 0x9a 0x78 0x56 0x34 0x12(低字节在前)。
- 你的
my_vprintf处理%lx格式符时,错误颠倒了高32位与低32位的读取顺序:正确逻辑应先读低32位0x9abcdef0、再读高32位0x12345678,但代码实际先读取高地址的0x12345678、再读低地址的0x9abcdef0,最终拼接成错误的0x9abcdef012345678。
3. 独立执行环境的标准库适配问题
编译参数使用了-nostartfiles -ffreestanding,意味着处于无操作系统的独立执行环境,GCC提供的标准va_list宏(如va_start/va_arg)可能未被正确初始化,或者你手动实现的可变参数处理逻辑未适配ARMv8-R的架构细节,导致无法正确解析寄存器和栈上的参数位置。
内容的提问来源于stack exchange,提问作者shifeng.yuan
相关产品推荐
相关产品推荐

