赞
踩
R0-R9:一般用于存储数据。R0-R3用于存储函数参数。
R10(sl):堆栈限制寄存器。
R11(fp):帧指针,指向栈顶。
R12(ip):内部过程调用寄存器。在函数分析和调用时暂时存储数据。
R13(sp):栈指针,指向栈底。
R14(lr):链接寄存器,保存函数返回地址。
R15(pc):程序计数器。
使用下面的测试程序来分析一下函数调用过程中的栈帧变化。
- #include<stdio.h>
-
- int test(int p){
- int a = p;
- return a;
- }
-
- int main(void){
- int a=1;
- test(a);
- return 0;
- }
经过反汇编后得到下面这一段汇编代码。直接从汇编代码中来分析函数栈帧的变化过程。
- 00008460 <test>:
- 8460: e1a0c00d mov ip, sp ;sp地址保存至ip
- 8464: e92dd800 stmdb sp!, {fp, ip, lr, pc} ;将 pc lr ip fp 依次入栈
- 8468: e24cb004 sub fp, ip, #4 ; 0x4
- 846c: e24dd008 sub sp, sp, #8 ; 分配栈空间
- 8470: e50b0010 str r0, [fp, #-16] ; 函数参数p R0入栈
- 8474: e51b3010 ldr r3, [fp, #-16]
- 8478: e50b3014 str r3, [fp, #-20] ; 变量a 入栈
- 847c: e51b3014 ldr r3, [fp, #-20] ; 变量a 出栈
- 8480: e1a00003 mov r0, r3 ; 变量a作为返回值赋给R0
- 8484: e24bd00c sub sp, fp, #12
- 8488: e89da800 ldmia sp, {fp, sp, pc} ; 将栈中保存的main函数的栈帧恢复到fp和sp,将lr赋给pc,返回main函数
-
- 0000848c <main>:
- 848c: e1a0c00d mov ip, sp ;sp地址保存至ip
- 8490: e92dd800 stmdb sp!, {fp, ip, lr, pc} ;将 pc lr ip fp 依次入栈
- 8494: e24cb004 sub fp, ip, #4 ; 0x4
- 8498: e24dd004 sub sp, sp, #4 ; 分配栈空间
- 849c: e3a03001 mov r3, #1 ; 0x1
- 84a0: e50b3010 str r3, [fp, #-16] ; 变量a入栈
- 84a4: e51b0010 ldr r0, [fp, #-16] ; 把a的值弹出给R0作为函数参数
- 84a8: ebffffec bl 8460 <test> ; 调用test函数,bl执行时会自动把pc+4赋给lr寄存器
- 84ac: e3a03000 mov r3, #0 ; 0x0
- 84b0: e1a00003 mov r0, r3 ; 0 作为返回值赋给R0
- 84b4: e89da808 ldmia sp, {r3, fp, sp, pc} ; 依次出栈,返回到init代码

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。