从最简单的实例学习ARM 指令集(四)
上一篇讲到子函数调用,这篇讲讲参数传递。先看下面一个小不点程序:test5.c#includevoid f1(int p1){}void main(){int d = 4;f1(d);} 然后编译:arm-linux-gnueabihf-gcc test.c -o test5 然后看看汇编代码:arm-linux-gnueabihf-objdump -
#include <stdio.h>
void f1(int p1)
{
}
void main()
{
int d = 4;
f1(d);
}
然后编译:arm-linux-gnueabihf-gcc test.c -o test5
然后看看汇编代码:arm-linux-gnueabihf-objdump -D test5
0000835c <f1>:
1 835c: b480 push {r7}
嚯,栈还预留这么多!真奢侈。
2 835e: b083 sub sp, #12
3 8360: af00 add r7, sp, #0
子函数f1来取主函数通过寄存器r0传过来的参数p1,并把它放到自己的栈上--也是一段内存:
4 8362: 6078 str r0, [r7, #4]
由于函数f1什么也没干,接下来就恢复盏指针,再恢复r7寄存器并返回:
5 8364: f107 070c add.w r7, r7, #12
6 8368: 46bd mov sp, r7
7 836a: bc80 pop {r7}
因为,f1自始至终都没有碰这个美少女lr,所以她还是主函数的:
8 836c: 4770 bx lr
9 836e: bf00 nop
00008370 <main>:
10 8370: b580 push {r7, lr}
11 8372: b082 sub sp, #8
12 8374: af00 add r7, sp, #0
13 8376: f04f 0304 mov.w r3, #4
14 837a: 607b str r3, [r7, #4]
把栈上的变量值搬到寄存器r0:
15 837c: 6878 ldr r0, [r7, #4]
16 837e: f7ff ffed bl 835c <f1>
17 8382: f107 0708 add.w r7, r7, #8
18 8386: 46bd mov sp, r7
19 8388: bd80 pop {r7, pc}
20 838a: bf00 nop
读者会发现,10行-14行与《从最简单的实例学习ARM 指令集(三)》里的test4.c是一样的。15行是新加的,目的是为了参数传递:
14行是把变量d的值,从寄存器r3搬到内存里--即栈上:
14 837a: 607b str r3, [r7, #4]
15行是把栈上的变量值搬到寄存器r0,以供子函数f1来取,你说这多折腾哪!直接用r3来传递不就少折腾一次吗,真是的!
15 837c: 6878 ldr r0, [r7, #4]
分析到这里,大家就明白了,arm使用寄存器r0来传递参数的。我们知道arm有r0-r16总共17个寄存器,他们都能用来传递参数吗? 看下面的例子:test6.c
#include <stdio.h>
void f1(int p1, int p2, int p3, int p4)
{
}
void main()
{
int d = 4;
f1(d, d, d, d);
}
然后编译:arm-linux-gnueabihf-gcc test.c -o test6
然后看看汇编代码:arm-linux-gnueabihf-objdump -D test6
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: f107 0714 add.w r7, r7, #20
836e: 46bd mov sp, r7
8370: bc80 pop {r7}
8372: 4770 bx lr
00008374 <main>:
8374: b580 push {r7, lr}
8376: b082 sub sp, #8
8378: af00 add r7, sp, #0
837a: f04f 0304 mov.w r3, #4
837e: 607b str r3, [r7, #4]
8380: 6878 ldr r0, [r7, #4]
8382: 6879 ldr r1, [r7, #4]
8384: 687a ldr r2, [r7, #4]
8386: 687b ldr r3, [r7, #4]
8388: f7ff ffe8 bl 835c <f1>
838c: f107 0708 add.w r7, r7, #8
8390: 46bd mov sp, r7
8392: bd80 pop {r7, pc}
看看,蓝色文字标注的main函数和f1函数,果然main函数的四个参数(d, d, d, d)是通过r0, r1, r2, r3 传递到子函数f1里的!
如果参数再多会怎么样?我们在下一篇文章里试试。
更多推荐
所有评论(0)