当前位置:   article > 正文

ARM C语言函数调用栈帧详解_arm 函数调用栈

arm 函数调用栈

1、ARM寄存器简介(用户模式)

        R0-R9:一般用于存储数据。R0-R3用于存储函数参数。

        R10(sl):堆栈限制寄存器。

        R11(fp):帧指针,指向栈顶。

        R12(ip):内部过程调用寄存器。在函数分析和调用时暂时存储数据。

        R13(sp):栈指针,指向栈底。

        R14(lr):链接寄存器,保存函数返回地址。

        R15(pc):程序计数器

2、函数调用栈帧

        使用下面的测试程序来分析一下函数调用过程中的栈帧变化。

  1. #include<stdio.h>
  2. int test(int p){
  3. int a = p;
  4. return a;
  5. }
  6. int main(void){
  7. int a=1;
  8. test(a);
  9. return 0;
  10. }

        经过反汇编后得到下面这一段汇编代码。直接从汇编代码中来分析函数栈帧的变化过程。

  1. 00008460 <test>:
  2. 8460: e1a0c00d mov ip, sp ;sp地址保存至ip
  3. 8464: e92dd800 stmdb sp!, {fp, ip, lr, pc} ;将 pc lr ip fp 依次入栈
  4. 8468: e24cb004 sub fp, ip, #4 ; 0x4
  5. 846c: e24dd008 sub sp, sp, #8 ; 分配栈空间
  6. 8470: e50b0010 str r0, [fp, #-16] ; 函数参数p R0入栈
  7. 8474: e51b3010 ldr r3, [fp, #-16]
  8. 8478: e50b3014 str r3, [fp, #-20] ; 变量a 入栈
  9. 847c: e51b3014 ldr r3, [fp, #-20] ; 变量a 出栈
  10. 8480: e1a00003 mov r0, r3 ; 变量a作为返回值赋给R0
  11. 8484: e24bd00c sub sp, fp, #12
  12. 8488: e89da800 ldmia sp, {fp, sp, pc} ; 将栈中保存的main函数的栈帧恢复到fp和sp,将lr赋给pc,返回main函数
  13. 0000848c <main>:
  14. 848c: e1a0c00d mov ip, sp ;sp地址保存至ip
  15. 8490: e92dd800 stmdb sp!, {fp, ip, lr, pc} ;将 pc lr ip fp 依次入栈
  16. 8494: e24cb004 sub fp, ip, #4 ; 0x4
  17. 8498: e24dd004 sub sp, sp, #4 ; 分配栈空间
  18. 849c: e3a03001 mov r3, #1 ; 0x1
  19. 84a0: e50b3010 str r3, [fp, #-16] ; 变量a入栈
  20. 84a4: e51b0010 ldr r0, [fp, #-16] ; 把a的值弹出给R0作为函数参数
  21. 84a8: ebffffec bl 8460 <test> ; 调用test函数,bl执行时会自动把pc+4赋给lr寄存器
  22. 84ac: e3a03000 mov r3, #0 ; 0x0
  23. 84b0: e1a00003 mov r0, r3 ; 0 作为返回值赋给R0
  24. 84b4: e89da808 ldmia sp, {r3, fp, sp, pc} ; 依次出栈,返回到init代码
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号