ARM ATPCS规则 栈分配 浅析

转自: http://blog.csdn.net/dance_rise/article/details/8450411

首先看一下面的代码:

ATPCS.c

[html]  view plain copy
  1. int func_1(int a, int b, int c, int d)  
  2. {  
  3.     return a + b + c + d;  
  4. }  
  5.   
  6. int func_2(int a, int b, int c, int d, int e, int f)  
  7. {  
  8.     return a + b + c + d + e + f;  
  9. }  
  10.   
  11. int main(int argc, char *argv[])  
  12. {  
  13.     func_1(11, 22, 33, 44);  
  14.     func_2(11, 22, 33, 44, 55, 66);  
  15.   
  16.     return 0;  
  17. }  
生成汇编代码:

[dance@localhost:~/linux_c/ATPCS]$ arm-linux-gcc -S ATPCS.c -o ATPCS.s

[dance@localhost:~/linux_c/ATPCS]$ vim ATPCS.s

[html]  view plain copy
  1. .arch armv4t  
  2.         .fpu softvfp  
  3.         .eabi_attribute 20, 1  
  4.         .eabi_attribute 21, 1  
  5.         .eabi_attribute 23, 3  
  6.         .eabi_attribute 24, 1  
  7.         .eabi_attribute 25, 1  
  8.         .eabi_attribute 26, 2  
  9.         .eabi_attribute 30, 6  
  10.         .eabi_attribute 18, 4  
  11.         .file   "ATPCS.c"  
  12.         .text  
  13.         .align  2  
  14.         .global func_1  
  15.         .type   func_1, %function  
  16. func_1:  
  17.         @ Function supports interworking.  
  18.         @ args = 0pretend = 0frame = 16  
  19.         @ frame_needed = 1uses_anonymous_args = 0   
  20.         @ link register save eliminated.        @ 表示不用保存lr  
  21.         str     fp, [sp, #-4]!          @ 保存main的fp, notice the "!", sp = sp - 4  
  22.         add     fp, sp, #0              @ 记录func_1的fp  
  23.         sub     sp, sp, #20             @ 划分func_1的栈空间  
  24.         str     r0, [fp, #-8]  
  25.         str     r1, [fp, #-12]  
  26.         str     r2, [fp, #-16]  
  27.         str     r3, [fp, #-20]  
  28.         ldr     r2, [fp, #-8]  
  29.         ldr     r3, [fp, #-12]  
  30.         add     r2, r2, r3  
  31.         ldr     r3, [fp, #-16]  
  32.         add     r2, r2, r3  
  33.         ldr     r3, [fp, #-20]  
  34.         add     r3, r2, r3  
  35.         mov     r0, r3  
  36.         add     sp, fp, #0              @ 将保存main的fp的位置赋值给sp  
  37.         ldmfd   sp!, {fp}               @ 还原main的fp,因为main函数的现场只有fp被改变  
  38.         bx      lr                      @ 返回main函数  
  39.         .size   func_1, .-func_1  
  40.         .align  2  
  41.         .global func_2  
  42.         .type   func_2, %function  
  43. func_2:  
  44.         @ Function supports interworking.  
  45.         @ args = 8pretend = 0frame = 16  
  46.         @ frame_needed = 1uses_anonymous_args = 0  
  47.         @ link register save eliminated.        @ 表示不用保存lr  
  48.         str     fp, [sp, #-4]!          @ 保存main的fp, notice the "!", sp = sp - 4  
  49.         add     fp, sp, #0              @ 记录func_2的fp  
  50.         sub     sp, sp, #20             @ 划分func_2的栈空间  
  51.         str     r0, [fp, #-8]  
  52.         str     r1, [fp, #-12]  
  53.         add     r2, r2, r3  
  54.         ldr     r3, [fp, #-16]          @ r3 = 33  
  55.         add     r2, r2, r3  
  56.         ldr     r3, [fp, #-20]          @ r3 = 44  
  57.         add     r2, r2, r3              @ 可以看到>4的参数是通过fp作为基址访问的  
  58.         ldr     r3, [fp, #4]            @ r3 = 55  
  59.         add     r2, r2, r3              @ 可以看到>4的参数是通过fp作为基址访问的  
  60.         ldr     r3, [fp, #8]            @ r3 = 66  
  61.         add     r3, r2, r3  
  62.         mov     r0, r3  
  63.         add     sp, fp, #0              @ 将保存main的fp的位置赋值给sp  
  64.         ldmfd   sp!, {fp}               @ 还原main的fp,因为main函数的现场只有fp被改变  
  65.         bx      lr                      @ 返回main函数  
  66.         .size   func_2, .-func_2  
  67.         .align  2  
  68.         .global main  
  69.         .type   main, %function  
  70. main:  
  71.         @ Function supports interworking.  
  72.         @ args = 0pretend = 0frame = 8  
  73.         @ frame_needed = 1uses_anonymous_args = 0  
  74.         stmfd   sp!, {fp, lr}           @ 保存main的被调函数的fp, lr,并回写sp  
  75.         add     fp, sp, #4              @ fp指向main栈空间的第一个单元  
  76.         sub     sp, sp, #16             @ 划分main的栈空间  
  77.         str     r0, [fp, #-8]           @ 保存argc  
  78.         str     r1, [fp, #-12]          @ 保存argv  
  79.         mov     r0, #11  
  80.         mov     r1, #22  
  81.         mov     r2, #33  
  82.         mov     r3, #44  
  83.         bl      func_1                  @ 调用func_1  
  84.         mov     r3, #55                 @ 将func_2中>4的参数保存在main的栈空间中  
  85.         str     r3, [sp, #0]  
  86.         mov     r3, #66  
  87.         str     r3, [sp, #4]            @ 将func_2中>4的参数保存在main的栈空间中  
  88.         mov     r0, #11  
  89.         mov     r1, #22  
  90.         mov     r2, #33  
  91.         mov     r3, #44  
  92.         bl      func_2                  @ 调用func_2  
  93.         mov     r3, #0  
  94.         mov     r0, r3  
  95.         sub     sp, fp, #4              @ sp 指向main的被调函数的fp, lr的保存位置  
  96.         ldmfd   sp!, {fp, lr}           @ 恢复main的被调函数的fp, lr  
  97.         bx      lr                      @ 返回main的被调函数  
  98.         .size   main, .-main  
  99.         .ident  "GCC: (Sourcery G++ Lite 2008q3-72) 4.3.2"  
  100.         .section        .note.GNU-stack,"",%progbits  
栈划分如下图所示:

ARM ATPCS规则 栈分配 浅析_第1张图片

总结:

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空间为什么没有使用???

你可能感兴趣的:(ARM ATPCS规则 栈分配 浅析)