分析单任务计算机操作之反汇编C程序

-中科大_243_石润成

本文旨在借助分析一段c语言程序反汇编代码来描述单任务计算机是如何工作的,不考虑中断等复杂操作。如有错误,希望读者能够反馈给我,不胜感激!         

1.预备阶段

本文以example.c为例,代码如下:

#include<stdio.h>
int g(int x)
{
    return x+3;
}
int f(int x)
{
    return g(x);
}
int main(void)
{
    return f(8)+1;
}

实验环境:Ubuntu10.04

工具:gccgdbmakefile

(1)编写makefile

                    

(2)make后生成预编译文件(*.cpp)、汇编文件(*.s)、目标文件(*.o)、执行文件elf文件

           

(3)example.s法看到实际的代码运行地址,本人使用gdbdisas反汇编查看.

命令: 

           # gdb example

           # disas main

           # disas f

           # disas g

main反汇编:

           

f函数反汇编:

           

g函数反汇编:

           

2.分析汇编代码

    从main入口函数开始执行,但切记在main函数并不是整个程序第一个执行的函数(详情请看点击打开链接)。

  从main函数反汇编可以看到,eip指向main函数地址0x080483d2

[以下整个内存地址由高到低展开]

#1     push %ebp                        //%ebp入栈,该ebp是调用main函数的基栈地址

         mov %esp,%ebp              //%ebp = %esp,ebp指向新函数的基栈地址,此时与esp一样指向栈底,用来保护整个函数的栈变量

                              

#2     sub $0x4,%esp                //esp = esp - 4,分配4个字节,由高地址向低地址分配

                              

#3    movl #0x8,(%esp)            //8存入esp所指的内存空间,即入栈,一般对于本函数来说就是个局部变量保存

                              

#4    call 0x80483bf <f>    等价于   push %eip                    

                                                       mov $0x80483bf,%eip 

    本机测试此时%eip为 0x080483e4,将其设为%eip_m表示当main调用f函数结束时返回main函数的下一个指(add $0x1,%eax)地址

                              

#5    push %ebp                         //同上所述,入栈保存main函数的基栈地址,此处设为exp_m

        mov %esp,%ebp               //同时ebp指向esp,ebp指向新的调用函数基栈地址,在此ebp和esp又开始维护新的函数栈空

                             

#6    sub $0x4,%esp                 //%esp = %esp - 4 [意味着申请了四个字节的空间]

                               

#7   /* %eax = %ebp + 8内存地址的值(8) */ 

       mov 0x8(%ebp),%eax     

       /* %eax入栈,即将8入栈,这里可以看到实参8传了过来,但是传给的函数f并没有直接使用原实参的8而是重新分配了一个空间保存,即所副本,函数参数传递为值传递。*/      

        mov %eax,(%esp)           


               

#8    call 0x80483b4 <g>  等价于  push %eip   

                                                      mov   $0x80483bf,%eip 

     本机测试此时%eip为 0x080483d0,将其设为%eip_f表示当f函数调用g函数结束时返回f函数的下一个指令(leave)地址

                             

#9     push %ebp                              //f函数的基栈地址入栈,此处用%ebp_f表示

      mov %esp,%ebp                     //ebp指向新的基栈地址%esp

                                       

#10   mov 0x8(%ebp),%eax            //%eax = ebp + 8 内存地址的值(即8)

         add $0x3,%eax                      //%eax = %eax +3 = 11

#11   pop %ebp                             // %ebp = %esp,esp = esp-4

        注意在pop之前,esp指向的是ebp_f即f函数的基栈地址,pop之后,ebp指向f函数的基栈地址。

                                      

#12    ret   等价于 pop %eip

         注意未ret之前,esp指向的是返回f函数的下一个指令的地址,即上述说的leave地址,ret后,eip将指向leave地址0x080483d0,此时程序会跳转到该处执行。

     此处,所申请的栈空间并没有释放掉,还有个8。

                                      

#13    leave 等价于 mov %ebp,%esp       //可以看到其实是在返回函数f将g函数的栈空间释放的

                               pop %ebp                  //ebp又恢复main函数的基站地址

                            

#14    ret   等价于 pop %eip         //eip指向返回main函数的下一个指令(add $0x1,%eax)地址eip:0x080483e4,并开始从此处执行


                                        

#15    leave  等价于 mov %ebp,%esp             // esp指向main函数的基地址

                                 pop %ebp                       //这里ebp将指向%ebp_x(调用main函数的基站地址)

                                 

                                          

3.总结

       这里简单总结一下,C语言是以函数为基本单元的,从本次实验分析来看,整个程序也是从一个函数进入到另一个函数的顺序调用,然后顺序返回,比如本次实验程序的main函数调用f函数,f函数调用g函数,g函数再反馈结果给f,f再反馈结果给main函数,然后程序结束,如下图所示。

                               

       值得注意的是,当一个函数跳转到另一个函数的时候,系统会利用寄存器来保存上下文,从本次实验中可以看到,寄存器ebp和esp一起用来保护函数的栈空间,通过esp来申请和释放栈空间,ebp来保存调用函数的基栈地址,当进行函数跳转时,会保存函数跳转处的下一条指令和基栈地址(入栈保存),这样在函数返回的时候可以根据栈的顺序来恢复调用函数的基地址,这里常用的汇编指令是leave,分析中我也提到,当函数返回到调用函数中时,会用leave指令来释放被调用函数的堆栈空间,并恢复自己的基地址,这样函数与函数之间的调用就能完好的单步执行下去,并能够进行相互传参返回,直到整个单任务程序结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值