32位Cortex R52架构下传递uint64_t类型函数参数异常是什么原因?
问题原因分析
根本原因:函数原型声明与定义不匹配导致的AAPCS调用约定传参错位
该问题和寄存器数量不足无关,核心是Cortex-R52遵循的32位Arm AAPCS(过程调用标准)的传参规则,加上调用侧可见的函数声明和实际函数定义不一致导致的参数位置错位:
- 32位AAPCS约定:
uint64_t这类8字节长度的参数,需要占用2个连续、且起始编号为偶数的通用寄存器传递,前4个参数优先用r0~r3寄存器传递,超出部分才会入栈。
正确原型下的参数寄存器分配规则
你给出的正确函数原型:
void read_func(uint8_t* read_buffer_ptr, uint64_t offset, size_t size);
三个参数的寄存器分配逻辑为:
- 第一个参数
read_buffer_ptr是32位指针,占用r0寄存器,下一个可用寄存器为r1 - 第二个参数
uint64_t offset是8字节类型,要求起始寄存器编号为偶数,因此跳过奇数编号的r1,占用r2(存低32位)、r3(存高32位) - 第三个参数
size_t size是32位类型,此时r0~r3已分配完毕,会被放到栈上传递
错误声明导致的传参错位
你提到此前写错了函数声明,意味着调用read_func的编译单元中,编译器看到的原型和实际定义不一致,比如误写为第二个参数是32位类型:
// 错误声明,调用侧编译器看到的版本 void read_func(uint8_t* read_buffer_ptr, uint32_t offset, size_t size);
此时编译器生成的传参逻辑为:
read_buffer_ptr占r0- 字面量0(32位)占r1
sizeof(read_buffer)占r2
而函数实现是按照uint64_t offset的原型去取参数,会直接从r2、r3寄存器读取offset的值:r2存的是sizeof(read_buffer)的值,r3是未被赋值的脏值,拼接后自然就是你观测到的随机值,和你在r5、r6中看到随机值的现象也吻合(函数内部会把r2、r3的值拷贝到被调用者保存的r5、r6寄存器中操作)。
为什么改成32位offset就正常?
当你把offset改为32位类型后,函数原型的参数长度和调用侧的声明匹配,参数分配逻辑统一:
read_buffer_ptr占r0- offset占r1
- size占r2
参数位置完全对齐,不会出现错位读脏值的问题,因此运行正常。
结论
该异常不是寄存器数量不足导致的,是函数声明与定义不匹配触发的调用约定传参错位问题。只需要确保所有调用read_func的位置都能看到正确的函数原型,即可解决该问题。
内容的提问来源于stack exchange,提问作者omkar kale
相关产品推荐
相关产品推荐

