- #include <stdio.h>
- void f1(int p1, int p2, int p3, int p4, int p5)
- {
- p5++;
- }
- void main()
- {
- int d = 4;
- f1(d, d, d, d, d);
- }
然后编译:arm-linux-gnueabihf-gcc test.c -o test7
然后看看汇编代码:arm-linux-gnueabihf-objdump -D test7
0000835c <f1>:
835c: b480 push {r7}
835e: b085 sub sp, #20
8360: af00 add r7, sp, #0
8362: 60f8 str r0, [r7, #12]
8364: 60b9 str r1, [r7, #8]
8366: 607a str r2, [r7, #4]
8368: 603b str r3, [r7, #0]
836a: 69bb ldr r3, [r7, #24]
836c: f103 0301 add.w r3, r3, #1
参数5是从母函数的栈里获取的:sp+20是自己新开辟的栈,而sp+24却是母函数的栈!
8370: 61bb str r3, [r7, #24]
接下来与前几篇讲过的一样,准备恢复老的r7,并返回母函数:
8372: f107 0714 add.w r7, r7, #20
8376: 46bd mov sp, r7
8378: bc80 pop {r7}
837a: 4770 bx lr
00008374 <main>:
1 8374: b580 push {r7, lr}
2 8376: b084 sub sp, #16
r7指向sp新开辟出来的空间的中间:
3 8378: af02 add r7, sp, #8
d = 4
4 837a: f04f 0304 mov.w r3, #4
存储d的值到自己的栈(内存): *(sp + (4 + 8) = r3
5 837e: 607b str r3, [r7, #4]
6 取出d的值,赋值给r3寄存器:
7 8380: 687b ldr r3, [r7, #4]
存储最后一个参数(参数5)到自己的栈: *(sp + 0) = r3
8 8382: 9300 str r3, [sp, #0]
r0-r3依次存储: (参数1,参数2,参数3,参数4):
9 8384: 6878 ldr r0, [r7, #4]
10 8386: 6879 ldr r1, [r7, #4]
11 8388: 687a ldr r2, [r7, #4]
12 838a: 687b ldr r3, [r7, #4]
13 838c: f7ff ffe6 bl 835c <f1>
14 8390: f107 0708 add.w r7, r7, #8
15 8394: 46bd mov sp, r7
16 8396: bd80 pop {r7, pc}
绿色的文字是上一篇讲过的,利用寄存器r0-r3存储4个参数到子函数f1。注意参数5的传递--蓝色文字描述的。编译器为了传递第5个参数,可谓“煞费苦心”,不惜让子函数访问母函数的栈内容。
这就是大于4个参数时,子函数调用参数传递的全部秘密。可够让编译器为难了,呵呵。 |