c文件到可执行文件运行的过程探索--堆栈中的过程活动记录

C语言在源码级别如何理解生成的文件在系统内是如何运行的?也就是各个函数是如何执行并调用,调用后返回到哪里?这里提到了 一个过程活动记录。

解决函数的调用的经典机制--堆栈中的过程活动记录。

过程活动记录是一种数据结构,记录了调用结束及返回调用点所需要的全部信息。

需要预习的知识:汇编指令、某处理器架构的寄存器、堆栈结构


inter的CPU架构寄存器:

4个32位通用寄存器(EAXEBXECXEDX)

2个32位变址和指针寄存器(ESIEDI) 2个32位指针寄存器(ESPEBP)

6个[16位(段选择符)+隐藏部分(描述符缓冲)]段寄存器(ESCSSSDSFSGS)

1个32位指令指针寄存器(EIP) 1个32位标志寄存器(EFlags)

2个48位系统表寄存器(GDTRIDTR)和2个[16位(选择符)+隐藏部分(描述符缓冲)](LDTRTR)

5个32位控制寄存器(CR0~ CR4),CR4是从Pentium CPU开始出现的

8个32位调试寄存器(DR0~ DR7)

8个32位测试寄存器(TR0~TR7)

arm的CPU架构寄存器:


汇编指令:pushl、movl、subl、leal、leave、ret

堆栈结构:先进后出。用到的指针寄存器是EIP、ESP、EBP。



案例:

#include "stdio.h"
int aa(int a,int b)
{
    int c = 0;
    c = a + b;
    return c;
}

int main(int argc,char**argv)
{
    int d = 0;
    int a  = 1;
    int b = 2;
    d = aa(a,b);
    return d;

}


gcc-4.5.1 x86的汇编代码

    .file    "test.c"//文件名
    .text//代码段
.globl aa//全局符号
    .type    aa, @function//定义aa为函数
aa:
    pushl    %ebp                                     //ebp中的内容压入堆栈(保护ebp中内容,上一个esp)
    movl    %esp, %ebp                          //esp中的内容传入ebp中(esp中的内容等于ebp),此时esp是什么?待定?
    subl    $16, %esp                              //esp中的内容减去16,并存入esp,也就是esp向下偏移16个字节,为什么是减?因为堆栈的生长方向和实际的物理地址的关系。向上生长的堆栈的实际物理地址在递减
    movl    $0, -4(%ebp)                        //ebp中的地址小4个偏移,写入0
    movl    12(%ebp), %eax                  //
    movl    8(%ebp), %edx
    leal    (%edx,%eax), %eax             //leal指令mov (%eax,%eax,4), %edx 就是把5这个地址里面的数读出来到edx ,lea (%eax,%eax,4), %edx 就是把5这个地址给edx,事实上就是一个算术运算。这里是把%edx+%eax赋值给%eax
    movl    %eax, -4(%ebp)                  //计算结果入栈
    movl    -4(%ebp), %eax                //保存返回值
    leave                                               //恢复ESP、EBP
    ret                                                     //POP IP
    .size    aa, .-aa
.globl main
    .type    main, @function
main:
    pushl    %ebp                               //ebp压栈,保存上一个调用的ebp,也就是上一个esp
    movl    %esp, %ebp                   //esp中的内容保存在ebp中,暂存此时的esp
    subl    $24, %esp                       //栈顶指针下沉24个字节,也就是6个双字,该空间是用来保存参数的?此时ESP在位置是EBP-24
    movl    $0, -4(%ebp)                   // 依次将临时变量存入栈中,               
    movl    $1, -8(%ebp)
    movl    $2, -12(%ebp)
    movl    -12(%ebp), %eax          //将其中一个传输给eax
    movl    %eax, 4(%esp)             //第一个实参
    movl    -8(%ebp), %eax
    movl    %eax, (%esp)                //第二个实参
    call    aa
    movl    %eax, -4(%ebp)//aa的返回值(存在eax)存入(-4)ebp
    movl    -4(%ebp), %eax//保存返回值?
    leave
    ret
    .size    main, .-main
    .ident    "GCC: (GNU) 4.5.1 20100924 (Red Hat 4.5.1-4)"
    .section    .note.GNU-stack,"",@progbits



arm-linux-gcc-4.5.1 arm的汇编代码

    .cpu arm1176jzf-s
    .eabi_attribute 27, 3
    .fpu vfp
    .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    "test.c"
    .text
    .align    2
    .global    aa
    .type    aa, %function
aa:
    @ args = 0, pretend = 0, frame = 16
    @ frame_needed = 1, uses_anonymous_args = 0
    @ link register save eliminated.
    str    fp, [sp, #-4]!
    add    fp, sp, #0
    sub    sp, sp, #20
    str    r0, [fp, #-16]
    str    r1, [fp, #-20]
    mov    r3, #0
    str    r3, [fp, #-8]
    ldr    r2, [fp, #-16]
    ldr    r3, [fp, #-20]
    add    r3, r2, r3
    str    r3, [fp, #-8]
    ldr    r3, [fp, #-8]
    mov    r0, r3
    add    sp, fp, #0
    ldmfd    sp!, {fp}
    bx    lr
    .size    aa, .-aa
    .align    2
    .global    main
    .type    main, %function
main:
    @ args = 0, pretend = 0, frame = 24
    @ frame_needed = 1, uses_anonymous_args = 0
    stmfd    sp!, {fp, lr}
    add    fp, sp, #4
    sub    sp, sp, #24
    str    r0, [fp, #-24]
    str    r1, [fp, #-28]
    mov    r3, #0
    str    r3, [fp, #-8]
    mov    r3, #1
    str    r3, [fp, #-12]
    mov    r3, #2
    str    r3, [fp, #-16]
    ldr    r0, [fp, #-12]
    ldr    r1, [fp, #-16]
    bl    aa
    str    r0, [fp, #-8]
    ldr    r3, [fp, #-8]
    mov    r0, r3
    sub    sp, fp, #4
    ldmfd    sp!, {fp, pc}
    .size    main, .-main
    .ident    "GCC: (ctng-1.8.1-FA) 4.5.1"
    .section    .note.GNU-stack,"",%progbits







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值