在我的汇编函数中,有6个参数。当我试图访问第四个和第五个参数时,它们是错误的,这是我在手臂皮层-8a上的代码。
push {r4-r8,lr}
ldr r6, [sp]
ldr r7, [sp, #4]我检查了sp内存,r4-r8有错误的值。但是,如果有3个或更少的参数,sp会给出正确的r4-r8值。我错过了什么吗?
发布于 2013-02-25 19:05:40
为什么不试试呢?
unsigned int fun ( unsigned int, unsigned int, unsigned int, unsigned int, unsigned int );
unsigned int myfun ( void )
{
return(fun(1,2,3,4,5));
}组装后拆卸
> arm-none-eabi-gcc -O2 -c fun.c -o fun.o
> arm-none-eabi-objdump -D fun.o 程序集输出
00000000 <myfun>:
0: e52de004 push {lr} ; (str lr, [sp, #-4]!)
4: e3a03005 mov r3, #5
8: e24dd00c sub sp, sp, #12
c: e58d3000 str r3, [sp]
10: e3a01002 mov r1, #2
14: e3a02003 mov r2, #3
18: e3a03004 mov r3, #4
1c: e3a00001 mov r0, #1
20: ebfffffe bl 0 <fun>
24: e28dd00c add sp, sp, #12
28: e49de004 pop {lr} ; (ldr lr, [sp], #4)
2c: e12fff1e bx lr前四个操作数按预期在寄存器r0-r3中。第五个操作数放在堆栈上。为什么编译器为操作数分配12个字节而不是4个字节,即看到函数的mystery...Perhaps更有意义:
unsigned int fun ( unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e )
{
return(a+b+c+d-e);
}拆装
arm-none-eabi-gcc -O2 -c fun.c -o fun.o
arm-none-eabi-objdump -D fun.o
00000000 <fun>:
0: e0811000 add r1, r1, r0
4: e0812002 add r2, r1, r2
8: e59d0000 ldr r0, [sp]
c: e0823003 add r3, r2, r3
10: e0600003 rsb r0, r0, r3
14: e12fff1e bx lr因此,被调用方只知道操作数是堆栈上的第一件事,而不关心调用方创建的堆栈帧。因此,为什么调用方分配12字节而不是4字节,这是一个谜。
arm-none-eabi-gcc --version
arm-none-eabi-gcc (GCC) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.看到编译器实际实现调用约定,可以更容易理解调用约定本身的读取。或者,如果您在您感兴趣的编译器上为您感兴趣的特定函数原型制作了这样的示例--您不需要阅读约定,您只需让您的调用方或被调用者--不管您感兴趣的是什么--匹配编译器正在为自己做的事情。
发布于 2013-02-25 16:46:05
额外的参数被传递到堆栈上,无论如何,SP将它们指向函数的条目。在prolog中,您正在推送要保存的寄存器,这会更改SP,因此需要对其进行解释。
r4、r5、r6、r7、r8和lr是6个寄存器,因此需要将SP偏移量调整为6×4=24个字节。因此,请尝试以下几点:
push {r4-r8,lr} // 6 regs are pushed
// SP is decremented by 6*4 = 24 bytes
ldr r6, [sp, #(0+24)] // get first stack arg
ldr r7, [sp, #(4+24)] // get second stack arg如果您使用SP执行更多操作,例如为堆栈vars分配空间,您可能也必须考虑到这一点。
发布于 2016-06-24 15:30:17
装甲运兵车标准
aapcs.pdf 5.5参数传递包含答案。
这并不是非常容易理解,因为它是一种算法,但回答这个问题的关键部分似乎是:
C.5如果NCRN小于r4,且NSAA等于SP,则在核心寄存器和堆栈之间拆分参数。参数的第一部分被应用到核心寄存器中,从NCRN开始,一直到包括r3。参数的其余部分被复制到堆栈中,从NSAA开始。NCRN设置为r4,NSAA由参数的大小减去寄存器中传递的数量增加。现在已经分配了这个论点。
就像其他人说的,意味着4个寄存器+堆栈。
https://stackoverflow.com/questions/15071506
复制相似问题