下面来看个例子,很简单的一个例子,但子函数有大量的形参(10个),以此来看看函数调用过程是如何做形参和实参的复制。
//main.c
#include <stdio.h>
int fun(int n0,int n1,int n2,int n3,int n4,int n5,int n6,int n7,int n8,int n9)
{
int m;
m=n0+n1+n2+n3+n4+n5+n6+n7+n8+n9;
return m;
}
void main(void)
{
int num;
num=fun(1,2,3,4,5,6,7,8,9,10);
}
在Linux操作系统下,经过arm-linux-gcc -S main.c -o main.s后,得到main.s:
//main.s
.arch armv4t
.fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "main.c"
.text
.align 2
.global fun
.type fun, %function
fun:
@ Function supports interworking.
@ args = 24, pretend = 0, frame = 24
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #28
str r0, [fp, #-16]
str r1, [fp, #-20]
str r2, [fp, #-24]
str r3, [fp, #-28]
ldr r2, [fp, #-16]
ldr r3, [fp, #-20]
add r2, r2, r3
ldr r3, [fp, #-24]
add r2, r2, r3
ldr r3, [fp, #-28]
add r2, r2, r3
ldr r3, [fp, #4]
add r2, r2, r3
ldr r3, [fp, #8]
add r2, r2, r3
ldr r3, [fp, #12]
add r2, r2, r3
ldr r3, [fp, #16]
add r2, r2, r3
ldr r3, [fp, #20]
add r2, r2, r3
ldr r3, [fp, #24]
add r3, r2, r3
str r3, [fp, #-8]
ldr r3, [fp, #-8]
mov r0, r3
add sp, fp, #0
ldmfd sp!, {fp}
bx lr
.size fun, .-fun
.align 2
.global main
.type main, %function
main:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr}
add fp, sp, #4 #这里是关键
sub sp, sp, #32 #这里是关键
mov r3, #5
str r3, [sp, #0]
mov r3, #6
str r3, [sp, #4]
mov r3, #7
str r3, [sp, #8]
mov r3, #8
str r3, [sp, #12]
mov r3, #9
str r3, [sp, #16]
mov r3, #10
str r3, [sp, #20]
mov r0, #1 #这里是关键
mov r1, #2 #这里是关键
mov r2, #3 #这里是关键
mov r3, #4 #这里是关键
bl fun
mov r3, r0
str r3, [fp, #-8]
sub sp, fp, #4
ldmfd sp!, {fp, lr}
bx lr
.size main, .-main
.ident "GCC: (ctng-1.6.1) 4.4.3"
.section .note.GNU-stack,"",%progbits
就是说,在arm编程里,函数调用过程中,子函数的参数值传递按顺序存放在r0,r1,r2,r3里,超过4个参数值传递放栈帧里(不多说了,有兴趣自己慢慢去看了)。