C语言 当在32位架构的函数中传递64位值作为参数时会发生什么?



我正面临一个奇怪的问题。我正在将uint64_t偏移量传递给32位架构(Cortex R52)上的函数。寄存器都是32位的。

这是函数。:对不起,我把函数声明弄乱了。

void read_func(uint8_t* read_buffer_ptr, uint64_t offset, size_t size);
main(){
// read_buffer : memory where something is read.
// read_buffer_ptr : points to read_buffer structure where value should be stored after reading value.
read_func(read_buffer_ptr, 0, sizeof(read_buffer));
}

在这个函数中,存储在offset中的值不是零,而是我在寄存器(r5, r6)中也看到的一些随机值。此外,当我使用offset作为32位值时,它工作得非常好。从r2,r3复制到r5,r6。

你能告诉我为什么会这样吗?登记还不够吗?

发布的原型是无效的,它应该是:

void read_func(uint8_t *read_buffer_ptr, uint64_t offset, size_t size);

同样,main()的定义也过时了:从c99开始不支持隐式的int返回类型,函数调用有另一个语法错误,缺少)

在32位架构上传递64位参数会发生什么是实现定义的:

  • 8字节的堆栈空间用来传递值
  • 或2个32位寄存器用于传递最低有效部分和最高有效部分
  • 或两者的组合取决于参数的数量
  • 或其他适合目标CPU的方案

在你的代码中,你传递0,它的类型是int,大概只有32位。如果read_func的原型是正确的,并且在函数调用之前被解析,这不是问题,否则行为是未定义的,C99编译器甚至不应该编译代码,但可能编译器只会发出警告并生成虚假代码。

在您的情况下(Cortex R52), 64位参数传递给寄存器r2和r3中的read_func

  1. Cortex-R52有32位地址总线,偏移量不能为64位。在计算中,只使用较低的32位,因为较高的32位不会产生任何影响。

例子:

uint64_t foo(void *buff, uint64_t offset, uint64_t size)
{
unsigned char *cbuff = buff;

while(size--)
{
*(cbuff++ + offset) = size & 0xff;
}
return offset + (uint32_t)cbuff;
}
void *z1(void);
uint64_t z2(void);
uint64_t z3(void);
uint64_t bar(void)
{
return foo(z1(), z2(), z3());
}
foo:
push    {r4, lr}
ldr     lr, [sp, #8]    //size
ldr     r1, [sp, #12]   //size
mov     ip, lr
add     r4, r0, r2     // cbuff + offset calculation r3 is ignored as not needed - processor has only 32bits address space.
.L2:
subs    ip, ip, #1     //size--
sbc     r1, r1, #0     //size--
cmn     r1, #1
cmneq   ip, #1
bne     .L3
add     r0, r0, lr
adds    r0, r0, r2
adc     r1, r3, #0
pop     {r4, pc}
.L3:
strb    ip, [r4], #1
b       .L2
bar:
push    {r0, r1, r4, r5, r6, lr}
bl      z1
mov     r4, r0      // buff
bl      z2
mov     r6, r0      // offset
mov     r5, r1      // offset
bl      z3
mov     r2, r6      // offset
strd    r0, [sp]    // size passed on the stack
mov     r3, r5      // offset
mov     r0, r4      // buff
bl      foo
add     sp, sp, #8
pop     {r4, r5, r6, pc}

可以看到电阻r2 &R3包含偏移量,r0 - buff和size在堆栈上。

最新更新