自然flw

linux内核学习之一 简单c语言反汇编

(我是第一次发技术博客的菜鸟,恳请大家指导!!)

一  由简单c程序生成汇编代码

首先给出本次我们要反汇编的简单c语言程序:(够简单吧~)

在linux环境中使用下面的命令条件编译:

生成汇编文件shiyan1.s:

shiyan1.s的部分代码截图:

全部粘贴出来如下:

 1 .file    "shiyan1.c"
 2     .text
 3     .globl    g
 4     .type    g, @function
 5 g:
 6 .LFB0:
 7     .cfi_startproc
 8     pushl    %ebp
 9     .cfi_def_cfa_offset 8
10     .cfi_offset 5, -8
11     movl    %esp, %ebp
12     .cfi_def_cfa_register 5
13     movl    8(%ebp), %eax
14     addl    $2, %eax
15     popl    %ebp
16     .cfi_restore 5
17     .cfi_def_cfa 4, 4
18     ret
19     .cfi_endproc
20 .LFE0:
21     .size    g, .-g
22     .globl    f
23     .type    f, @function
24 f:
25 .LFB1:
26     .cfi_startproc
27     pushl    %ebp
28     .cfi_def_cfa_offset 8
29     .cfi_offset 5, -8
30     movl    %esp, %ebp
31     .cfi_def_cfa_register 5
32     subl    $4, %esp
33     movl    8(%ebp), %eax
34     movl    %eax, (%esp)
35     call    g
36     leave
37     .cfi_restore 5
38     .cfi_def_cfa 4, 4
39     ret
40     .cfi_endproc
41 .LFE1:
42     .size    f, .-f
43     .globl    main
44     .type    main, @function
45 main:
46 .LFB2:
47     .cfi_startproc
48     pushl    %ebp
49     .cfi_def_cfa_offset 8
50     .cfi_offset 5, -8
51     movl    %esp, %ebp
52     .cfi_def_cfa_register 5
53     subl    $4, %esp
54     movl    $1, (%esp)
55     call    f
56     addl    $3, %eax
57     leave
58     .cfi_restore 5
59     .cfi_def_cfa 4, 4
60     ret
61     .cfi_endproc
62 .LFE2:
63     .size    main, .-main
64     .ident    "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
65     .section    .note.GNU-stack,"",@progbits
View Code

去除链接信息的汇编代码:

 1 g:
 2     pushl    %ebp
 3     movl    %esp, %ebp
 4     movl    8(%ebp), %eax
 5     addl        $2, %eax
 6     popl      %ebp
 7     ret
 8 f:    
 9     pushl    %ebp
10     movl    %esp, %ebp
11     subl        $4, %esp
12     movl    8(%ebp), %eax
13     movl    %eax, (%esp)
14     call       g
15     leave
16     ret
17 main:
18     pushl    %ebp
19     movl    %esp, %ebp
20     subl     $4, %esp
21     movl    $1, (%esp)
22     call        f
23     addl     $3, %eax
24     leave
25     ret

二  汇编代码分析

     前提:基于32位的系统,相关的寄存器也为32位

           寄存器介绍:eax  >> 累加器

                           ebp  >> 堆栈基指针

                           esp  >> 堆栈顶指针

                           eip   >> 指向待执行的下一条指令,相当于pc

           汇编指令介绍:

          

             

     代码分析:我们都知道c语言代码是从main()函数开始执行的,汇编也不例外,找到main 的标志处,即第17行的位置。

ebp(0)
1
eip(第23行)
ebp(1)
1
eip(第15行)
ebp(4)
 
 
 

   栈示意图

栈向下增长,即在内存中由高地址向低地址生长,具体为什么还在探索,为了简化,从上向下依次编号0,1,2,3,4,5,6,7 ....实际对应内存中的32位地址开始时为空栈,ebp,esp都是指向上面示意图中最上面,即ebp=0,esp=0,首先 

        pushl %ebp               ;ebp的值入栈,如上图          

        movl %esp, %ebp       ;ebp也指向esp的位置,即ebp=1     

        subl  $4, %esp            ;esp向下移动一格(寄存器为32位)

        movl $1, (%esp)          ;数值1 入栈

        call     f                      ;程序流程发生跳转,此时eip中保存的是下一条指令的地址(保证函数能够正确返回),为方便理解,上图中表示为第23行代码,下面即开始执行f子函数

        pushl   %ebp                 ;ebp的值(为1)入栈,此时栈顶指针esp=4       

        movl    %esp, %ebp         ;将esp的值赋给ebp,即ebp也指向4的位置

        subl     $4, %esp           ;esp向下移动一个位置,为5

        movl    8(%ebp), %eax      ;变址寻址,取ebp指向的栈中退回两格的值,为1,赋给累加器eax

         movl   %eax, (%esp)       ;将累加器eax中的值1入栈,如上图所示

         call    g                        ;程序流程再次发生跳转,此时eip中保存的是下一条指令的地址, 代码中的第15行,接下来执行子函数g中的代码

 

         pushl   %ebp                 ;将ebp的值入栈,此时ebp指向4的位置,即将4入栈,此时esp  为7 ,指向如上图所示

          movl %esp, %ebp          ;ebp也指向esp的位置

          movl 8(%ebp), %eax       ;变址寻址,取ebp指向的栈中退回两格的值,为1,赋给累加器eax   

          addl     $2, %eax             ;累加器中的值加2

          popl   %ebp                    ;ebp重新指向4的位置

          ret                                 ;eip指的位置(第15行代码),函数流程跳转,函数返回

 

         leave                               ;esp也指向ebp的位置 ,指向4的位置,ebp出栈,ebp指向1的位置

         ret                                   ;函数返回,eip的值(第23代码在内存中的地址)出栈,程序流程发生跳转

          

         leave  

          ret                                  ;栈回到初始状态

   上述分析过程相关的视频讲解链接已经附在文章最后。

三  总结

个人对计算机如何工作的理解:

       计算机的工作离不开硬件和软件。软件支配硬件,要使计算机按照我们的意愿工作,首先我们先要将我们的意愿传达给计算机,这就是编程。但是计算机只能识别0和1,但是我们为了编程方便,设计的高级语言,这就需要一个翻译的工具,将高级语言翻译成计算机能够识别的机器语言(0和1),这就是编译器。编译器将一系列指令翻译成机器能识别的指令,cpu再从内存中取指令和数据,进行相应运算,再将结果回存,再取指,执行,回存。。。。

        第一次发博客,水平有限,错误之处恳请指导!!

 

 

 

 

 

 

方龙伟

原创作品 转载请注明出处 

Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                           

 

posted on 2016-02-25 19:10  自然flw  阅读(1616)  评论(0编辑  收藏  举报

导航