加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

linux反汇编

(2014-02-16 13:03:00)
方式一:使用gcc
gcc编译有四步走,预编译,编译,汇编,连接
使用-S编译选项
    gcc  -S  test.c
会在当前目录下生成test.s的文件,该文件即是相应的汇编程序


方式二:使用gdb
首先编译时要是用-g编译选项
    gcc -g ./test.c  -o ./test
接着运行gdb
    gdb ./test--(可执行文件)

在gdb中使用 disassemble + frame(帧),即可查看相应代码段的汇编代码
frame通常为一个函数名。




方式三:使用objdump

命令为 objdump -d test.o--(目标文件)
或者  objdump -d  test--(可执行文件)






一个反汇编代码解释:
(本例使用的GCC的汇编格式,这种格式叫做GAS(GNU ASsembler ,GNU汇编器) )

c语言代码如下:
------test.c-------

#include
#include
int static_var = 5;

int 
fun_ret_int(int a, int b, register int c)
{
    int d=1;
    return a+b+c+d;    
}

void fun()
{
     int i1, i2, i3, i4,i5, i6,i7,i8,i9,i10;
    i1=1;i2=3;i3=5; i4=7;i5=9; i6=11;i7=13;i8=15;i9=17;i10=19;
     int i;
     for(i=11; i< 20;++i);
     i2 = fun_ret_int(1, 2, i1);    
}

int main(int argc ,char *argv[])
{
    int i =1; 
    int b =2;
    argc = 3;
    char **a=argv;
    fun();
    return 0;
}


现在编译:
    gcc  test.c -o test
反汇编 :
    objdump -d test
    
    
    
我截取部分代码如下:

08048394 :
 8048394:    55                       push   �p
 8048395:    89 e5                    mov    %esp,�p
 8048397:    83 ec 10                 sub    $0x10,%esp
 804839a:    8b 4d 10                 mov    0x10(�p),�x
 804839d:    c7 45 fc 01 00 00 00     movl   $0x1,-0x4(�p)
 80483a4:    8b 45 0c                 mov    0xc(�p),�x
 80483a7:    8b 55 08                 mov    0x8(�p),�x
 80483aa:    8d 04 02                 lea    (�x,�x,1),�x
 80483ad:    01 c8                    add    �x,�x
 80483af:    03 45 fc                 add    -0x4(�p),�x
 80483b2:    c9                       leave  
 80483b3:    c3                       ret    

080483b4 :
 80483b4:    55                       push   �p
 80483b5:    89 e5                    mov    %esp,�p
 80483b7:    83 ec 3c                 sub    $0x3c,%esp
 80483ba:    c7 45 fc 01 00 00 00     movl   $0x1,-0x4(�p)
 80483c1:    c7 45 f8 03 00 00 00     movl   $0x3,-0x8(�p)
 80483c8:    c7 45 f4 05 00 00 00     movl   $0x5,-0xc(�p)
 80483cf:    c7 45 f0 07 00 00 00     movl   $0x7,-0x10(�p)
 80483d6:    c7 45 ec 09 00 00 00     movl   $0x9,-0x14(�p)
 80483dd:    c7 45 e8 0b 00 00 00     movl   $0xb,-0x18(�p)
 80483e4:    c7 45 e4 0d 00 00 00     movl   $0xd,-0x1c(�p)
 80483eb:    c7 45 e0 0f 00 00 00     movl   $0xf,-0x20(�p)
 80483f2:    c7 45 dc 11 00 00 00     movl   $0x11,-0x24(�p)
 80483f9:    c7 45 d8 13 00 00 00     movl   $0x13,-0x28(�p)
 8048400:    c7 45 d4 01 00 00 00     movl   $0x1,-0x2c(�p)
 8048407:    c7 45 d0 0b 00 00 00     movl   $0xb,-0x30(�p)
 804840e:    eb 04                    jmp    8048414
 8048410:    83 45 d0 01              addl   $0x1,-0x30(�p)
 8048414:    83 7d d0 13              cmpl   $0x13,-0x30(�p)
 8048418:    7e f6                    jle    8048410
 804841a:    8b 45 fc                 mov    -0x4(�p),�x
 804841d:    89 44 24 08              mov    �x,0x8(%esp)
 8048421:    c7 44 24 04 02 00 00     movl   $0x2,0x4(%esp)
 8048428:    00 
 8048429:    c7 04 24 01 00 00 00     movl   $0x1,(%esp)
 8048430:    e8 5f ff ff ff           call   8048394
 8048435:    89 45 f8                 mov    �x,-0x8(�p)
 8048438:    c9                       leave  
 8048439:    c3                       ret    

0804843a :
 804843a:    55                       push   �p
 804843b:    89 e5                    mov    %esp,�p
 804843d:    83 ec 10                 sub    $0x10,%esp
 8048440:    c7 45 fc 01 00 00 00     movl   $0x1,-0x4(�p)
 8048447:    c7 45 f8 02 00 00 00     movl   $0x2,-0x8(�p)
 804844e:    c7 45 08 03 00 00 00     movl   $0x3,0x8(�p)
 8048455:    8b 45 0c                 mov    0xc(�p),�x
 8048458:    89 45 f4                 mov    �x,-0xc(�p)
 804845b:    e8 54 ff ff ff           call   80483b4
 8048460:    b8 00 00 00 00           mov    $0x0,�x
 8048465:    c9                       leave  
 8048466:    c3                       ret    
 8048467:    90                       nop
 8048468:    90                       nop
 8048469:    90                       nop
 804846a:    90                       nop
 804846b:    90                       nop
 804846c:    90                       nop
 804846d:    90                       nop
 804846e:    90                       nop
 804846f:    90                       nop

    
现在尝试对其中的一些语句进行分析:

在每个函数的开始部分都是:
push   �p
mov    %esp,�p
sub    $***,%esp

�p---是帧寄存器,在函数中就是函数的基址寄存器,指向一个函数的栈底(帧底)。
%esp---是栈寄存器,相当于是整个程序的基址寄存器,始终指向栈顶。
push---入栈操作。
mov ---移动
sub ---减法

第一句话 push   �p 的意思是�p入栈,此时的�p保存的是上一个函数的帧起始地址,也即调用该函数的地址。
把�p压栈,保存起来,以便返回。

第二句  mov    %esp,�p 的意思是  把%esp赋值给�p,%esp保存的是当前程序的栈顶,也即该函数所占用内存的起始地址。
把%esp赋值给�p,也就把�p设置成了当前函数的帧起始地址。

第三句话sub    $***,%esp,并不会在每个程序中都会出现。可以尝试一下,如果一个函数没有任何局部变量,那么反汇编这句话也就
不会出来。这句话的意思是,把%esp减去一个数。我们知道栈空间是由高到底发展的,所以%esp++,相当于%esp=%esp-1。因为调用了新函数,而且该函数有局部变量,那么栈空间就变大了,所以要扩展栈空间,也即是修改%esp,让其指向更低的地址。而让%esp减去多少呢?这要看函数占用多少空间,于其中的局部变量有关,以及他将调用的函数参数有关。其并不计算其参数所占的空间,其参数所占的空间要算在调用它的函数中。


下面来看看参数的压栈顺序;

函数fun中语句:
     i2 = fun_ret_int(1, 2, i1);
所对应的汇编如下:
 804841a:    8b 45 fc                 mov    -0x4(�p),�x  
 804841d:    89 44 24 08              mov    �x,0x8(%esp)
 8048421:    c7 44 24 04 02 00 00     movl   $0x2,0x4(%esp)
 8048428:    00 
 8048429:    c7 04 24 01 00 00 00     movl   $0x1,(%esp)
 8048430:    e8 5f ff ff ff           call   8048394
 
从这个汇编中可以看出函数参数的入栈顺序是自左往右的。
    
mov    -0x4(�p),�x  是把i1 放到�x 寄存器中
mov    �x,0x8(%esp)   是把�x压栈,所以这句话是把i1放在距离%esp为8byte的地方,即8~12byte存放的是一个i1(int)
movl   $0x2,0x4(%esp)   距%esp 4~8byte存放的是2(int)
movl   $0x1,(%esp)      距%esp 0~4byte存放的是1(int)

因为栈是由高到低的,且%esp始终指向栈顶。所以看出入栈顺序是i1,2,1。正好与c文件中fun函数的参数顺序相反。
自右向左压栈有什么好处呢?第一,由于栈是FILO,所以反方向入栈,那么第一个参数也就距离%esp越近。每次取参数时也就很方便,不用把所有参数占用的空间都计算出来,然后在取。第二,当传递的参数过多时,每次都从栈顶计算,取适当位置的参数,其他便可忽略。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有