首先看一下面的代码:
ATPCS.c
- int func_1(int a, int b, int c, int d)
- {
- return a + b + c + d;
- }
- int func_2(int a, int b, int c, int d, int e, int f)
- {
- return a + b + c + d + e + f;
- }
- int main(int argc, char *argv[])
- {
- func_1(11, 22, 33, 44);
- func_2(11, 22, 33, 44, 55, 66);
- return 0;
- }
[dance@localhost:~/linux_c/ATPCS]$ arm-linux-gcc -S ATPCS.c -o ATPCS.s
[dance@localhost:~/linux_c/ATPCS]$ vim ATPCS.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 "ATPCS.c"
- .text
- .align 2
- .global func_1
- .type func_1, %function
- func_1:
- @ Function supports interworking.
- @ args = 0, pretend = 0, frame = 16
- @ frame_needed = 1, uses_anonymous_args = 0
- @ link register save eliminated. @ 表示不用保存lr
- str fp, [sp, #-4]! @ 保存main的fp, notice the "!", sp = sp - 4
- add fp, sp, #0 @ 记录func_1的fp
- sub sp, sp, #20 @ 划分func_1的栈空间
- str r0, [fp, #-8]
- str r1, [fp, #-12]
- str r2, [fp, #-16]
- str r3, [fp, #-20]
- ldr r2, [fp, #-8]
- ldr r3, [fp, #-12]
- add r2, r2, r3
- ldr r3, [fp, #-16]
- add r2, r2, r3
- ldr r3, [fp, #-20]
- add r3, r2, r3
- mov r0, r3
- add sp, fp, #0 @ 将保存main的fp的位置赋值给sp
- ldmfd sp!, {fp} @ 还原main的fp,因为main函数的现场只有fp被改变
- bx lr @ 返回main函数
- .size func_1, .-func_1
- .align 2
- .global func_2
- .type func_2, %function
- func_2:
- @ Function supports interworking.
- @ args = 8, pretend = 0, frame = 16
- @ frame_needed = 1, uses_anonymous_args = 0
- @ link register save eliminated. @ 表示不用保存lr
- str fp, [sp, #-4]! @ 保存main的fp, notice the "!", sp = sp - 4
- add fp, sp, #0 @ 记录func_2的fp
- sub sp, sp, #20 @ 划分func_2的栈空间
- str r0, [fp, #-8]
- str r1, [fp, #-12]
- add r2, r2, r3
- ldr r3, [fp, #-16] @ r3 = 33
- add r2, r2, r3
- ldr r3, [fp, #-20] @ r3 = 44
- add r2, r2, r3 @ 可以看到>4的参数是通过fp作为基址访问的
- ldr r3, [fp, #4] @ r3 = 55
- add r2, r2, r3 @ 可以看到>4的参数是通过fp作为基址访问的
- ldr r3, [fp, #8] @ r3 = 66
- add r3, r2, r3
- mov r0, r3
- add sp, fp, #0 @ 将保存main的fp的位置赋值给sp
- ldmfd sp!, {fp} @ 还原main的fp,因为main函数的现场只有fp被改变
- bx lr @ 返回main函数
- .size func_2, .-func_2
- .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} @ 保存main的被调函数的fp, lr,并回写sp
- add fp, sp, #4 @ fp指向main栈空间的第一个单元
- sub sp, sp, #16 @ 划分main的栈空间
- str r0, [fp, #-8] @ 保存argc
- str r1, [fp, #-12] @ 保存argv
- mov r0, #11
- mov r1, #22
- mov r2, #33
- mov r3, #44
- bl func_1 @ 调用func_1
- mov r3, #55 @ 将func_2中>4的参数保存在main的栈空间中
- str r3, [sp, #0]
- mov r3, #66
- str r3, [sp, #4] @ 将func_2中>4的参数保存在main的栈空间中
- mov r0, #11
- mov r1, #22
- mov r2, #33
- mov r3, #44
- bl func_2 @ 调用func_2
- mov r3, #0
- mov r0, r3
- sub sp, fp, #4 @ sp 指向main的被调函数的fp, lr的保存位置
- ldmfd sp!, {fp, lr} @ 恢复main的被调函数的fp, lr
- bx lr @ 返回main的被调函数
- .size main, .-main
- .ident "GCC: (Sourcery G++ Lite 2008q3-72) 4.3.2"
- .section .note.GNU-stack,"",%progbits
总结:
1.每个函数的第一条语句是保存其被调函数的现场
2.生成当前函数的fp,fp记录当前函数所在栈空间的开始位置,即上一个函数的sp+4
3.当前函数的参数<=4时参数通过寄存器r0 - r4传递
4.当前函数的参数>=4时参数通过当前函数的被调函数栈空间传递
5.当前函数访问>=4的参数是通过fp作为基地址的
6.函数的返回值是通过r0返回
7.函数的最后先回复当前函数的被调函数的现场,再返回被调函数
问题:
func_1和func_2中fp_func - 4空间为什么没有使用???