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

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

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

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

生成汇编文件shiyan1.s:

shiyan1.s的部分代码截图:

全部粘贴出来如下:

 .file    "shiyan1.c"
.text
.globl g
.type g, @function
g:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset
.cfi_offset , -
movl %esp, %ebp
.cfi_def_cfa_register
movl (%ebp), %eax
addl $, %eax
popl %ebp
.cfi_restore
.cfi_def_cfa ,
ret
.cfi_endproc
.LFE0:
.size g, .-g
.globl f
.type f, @function
f:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset
.cfi_offset , -
movl %esp, %ebp
.cfi_def_cfa_register
subl $, %esp
movl (%ebp), %eax
movl %eax, (%esp)
call g
leave
.cfi_restore
.cfi_def_cfa ,
ret
.cfi_endproc
.LFE1:
.size f, .-f
.globl main
.type main, @function
main:
.LFB2:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset
.cfi_offset , -
movl %esp, %ebp
.cfi_def_cfa_register
subl $, %esp
movl $, (%esp)
call f
addl $, %eax
leave
.cfi_restore
.cfi_def_cfa ,
ret
.cfi_endproc
.LFE2:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits

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

 g:
pushl %ebp
movl %esp, %ebp
movl (%ebp), %eax
addl $, %eax
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
subl $, %esp
movl (%ebp), %eax
movl %eax, (%esp)
call g
leave
ret
main:
pushl %ebp
movl %esp, %ebp
subl $, %esp
movl $, (%esp)
call f
addl $, %eax
leave
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

linux内核学习之一 简单c语言反汇编的更多相关文章

  1. Linux内核分析——Linux内核学习总结

    马悦+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核学习总结 一 ...

  2. Linux 内核学习的经典书籍及途径

    from:http://www.zhihu.com/question/19606660 知乎 Linux 内核学习的经典书籍及途径?修改 修改 写补充说明 举报   添加评论 分享 • 邀请回答   ...

  3. 关于Linux内核学习的误区以及相关书籍介绍

    http://www.hzlitai.com.cn/article/ARM9-article/system/1605.html 写给Linux内核新手-关于Linux内核学习的误区 先说句正经的:其实 ...

  4. linux内核学习之一:环境搭建--安装Debian7.3

    本系列文章假设读者已对linux有一定的了解,其实学习linux内核不需要有很深的关于linux的知识,只需要了解以下内容:linux基础知识及基本shell命令:现代操作系统的基本概念:C语言和gc ...

  5. Linux 内核学习经验总结

    Linux 内核学习经验总结 学习内核,每个人都有自己的学习方法,仁者见仁智者见智.以下是我在学习过程中总结出来的东西,对自身来说,我认为比较有效率,拿出来跟大家交流一下. 内核学习,一偏之见:疏漏难 ...

  6. 关于Linux内核学习的一点点总结

    关于Linux内核学习的一点点总结 关键词:Linux, 操作系统,内核 博客列表 由反汇编C程序来理解计算机是如何工作的 通过分析一个简化版时间片轮转多道程序内核代码来认识操作系统中的进程调度 通过 ...

  7. Linux 内核 链表 的简单模拟(1)

    第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct stu ...

  8. linux内核学习之二:编译内核

    在linux内核学习系列的第一课中讲述了搭建学习环境的过程(http://www.cnblogs.com/xiongyuanxiong/p/3523306.html),环境搭好后,马上就进入到下一环节 ...

  9. Linux内核学习笔记-2.进程管理

    原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

随机推荐

  1. 如何在WPF的DiagramControl中绘制一个类型数据关系图的方法

    https://www.devexpress.com/Support/Center/Question/Details/T418156 虽然是在wpf中,但是在win中也可以调用wpf控件,这个太棒了, ...

  2. 深入理解IOC模式及Unity框架

    研究了下,有几篇博客确实已经说得很清楚了 1.IoC模式:http://www.cnblogs.com/qqlin/archive/2012/10/09/2707075.html  这篇博客是通过一个 ...

  3. Manual——Test (翻译1)

    LTE Manual ——Logging(翻译) (本文为个人学习笔记,如有不当的地方,欢迎指正!) 1.17.3 Testing framework(测试框架)   ns-3 包含一个仿真核心引擎. ...

  4. SVN使用手册

    安装Tortoise SVN Icon TortoiseSVN 1.7版本及之后与之前的版本有很大的变化,主要区别如下: 1.7以前的版本会在每个目录中生成一个.svn的隐藏目录.1.7及以后的版本, ...

  5. linux node安装

    安装node0.10.24版本,升级了两个版本/usr/local/src/node/0.10.24/usr/local/n/versions/node/4.4.7/usr/local/n/versi ...

  6. Spring的注解

    Action想使用serviceImpl时,都需要最原始的方法New一个接口,Service service = new serviceImpl();去实例化service了.都需要Action主动创 ...

  7. Centos 与本地终端 上传、下载 文件

    首先安装lrzsz # yum -y install lrzsz 1.上传文件,执行命令rz,会跳出文件选择窗口,选择好文件,点击确认即可. # rz 运行rz命令后弹出选择文件窗口,找到要上传的文件 ...

  8. Java_I/O输入输出_使用输入输出流读取文件,将一段文字加密后存入文件,然后读取,将加密前与后的文件输出

    import java.io.*; public class Example { public static void main(String[] args) { char a[] = "今 ...

  9. 数字图像处理作业使用OpenCV - 配置

    使用环境:Windows7 旗舰版 + vs2008 + OpenCV2.0a 基本上配置都是通过网上一个教程,在此附上地址 Click ME. 为了避免因不同版本而出现的安装问题,我还是下载了2.0 ...

  10. javac 导入第三方jar包

    如果是导入一个包,只需要 javac -classpath xxx/xxx/xxx.jar xxx.java 即可 如果有多个包,windows下用分号隔开,Lunix下用冒号隔开即可.