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

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

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

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

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

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

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

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

        R15(pc):程序计数器。

2、函数调用栈帧

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

#include

int test(int p){
        int a = p;
        return a;
}

int main(void){
        int a=1;
        test(a);
        return 0;
}

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

00008460 :
    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 
: 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函数,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代码

你可能感兴趣的:(linux,系统,gnu,服务器,linux,c语言,arm)