SJTUBEAR 原创作品转载请注明出处 /《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

1. 汇编

在修习LINUX内核这门课的初始阶段,首先需要掌握的就是汇编以及汇编程序对于堆栈的操作。

下面我们就来分析一下一个简单地C程序是如何被汇编程序所表达的!

2. 得到汇编代码

首先,我们写一个简单地C程序,命名为exp1.c:

 #include <stdio.h>

 int g(int x)
{
return x+;
} int f(x)
{
return g(x);
} int main()
{
return f()+;
}

程序非常的简单,我们此时再通过编译指令将其编译为汇编程序:

 gcc –S –o main.s main.c -m32

这样我们就得到了这个简单C程序的汇编代码:

     .file    "exp1.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_def_cfa ,
.cfi_restore
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/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",@progbits

3.汇编代码分析

汇编出的代码,多了很多辅助信息,为了能够更好地看清主干,我们删减一下:

 g:
pushl %ebp //保存现场,将父函数的栈底寄存器存入当前程序栈中
movl %esp, %ebp //构建当前函数堆栈
movl (%ebp), %eax //从父函数堆栈中取得参数,存入ax寄存器
addl $, %eax //完成+3操作
popl %ebp //恢复原父函数堆栈
ret //pop出原EIP地址,恢复执行
f:
pushl %ebp //保存现场,将父函数的栈底寄存器存入当前程序栈中
movl %esp, %ebp //构建当前函数堆栈
subl $, %esp //栈顶加一,用以储存变量传递给g函数
movl (%ebp), %eax //取得参数
movl %eax, (%esp) //将参数传入变量位置
call g //调用g
leave //清楚局部变量空间
ret //返回
main:
pushl %ebp
movl %esp, %ebp
subl $, %esp //空出局部变量空间
movl $, (%esp) //为变量赋值
call f //调用f
addl $, %eax //完成+1操作
leave //清理局部变量
ret //返回

我们对f函数进行详细的分析:

1. 首先进行enter指令:

此时,ebp当前所指向的位置存入栈顶,并且将ebp重定向指向esp:

2.栈顶加一并存入变量值:

3.调用g

4.从g返回后,返回值储存在AX寄存器中,不用操作,调用leave,清理变量

5.最后ret,同时EIP被读出恢复到原位置继续执行,返回值在AX中传递给调用函数

3.个人的一点感悟:

程序的调用就是这样嵌套的执行下去,每个函数都有自己的堆栈用以储存当前变量以及环境值,并通过将父函数的EBP放入栈底用以恢复环境。

同时EIP存入父栈栈顶,便于恢复到原节点处继续执行。

这样,就可以有规律的一直嵌套下去。

如果使用递归函数,就是一个码堆栈的过程,知道最顶部的堆栈返回,函数就像多米诺骨牌一样收回所有的堆栈。

这也是递归函数占用空间比较多的原因之一。如果没有很好地退出机制,有可能内存溢出。

C程序汇编运行模式简析的更多相关文章

  1. Hadoop_20_MapReduce程序的运行模式

    1.MapReduce程序的运行模式 1. Windows中运行MapReduce程序 (1)mapreduce程序是被提交给LocalJobRunner在本地以单进程的形式运行 (2)而处理的数据及 ...

  2. DirectShow程序运行过程简析

    这段时间一直在学习陆其明老师的<DirectShow开发指南>一书,书中对DirectShow的很多细节讲解清晰,但是却容易让人缺少对全局的把握.在学习过程中,整理了关于DirectSho ...

  3. Qt- 图形界面应用程序的运行模式

    main() 定义主窗口 ————>fd = DefineMainWindow() 创建主窗口————>win = CreateMainWindow() 创建主窗口中的元素-----> ...

  4. Hadoop-MR[会用]MR程序的运行模式

    1.简介 现在很少用到使用MR计算框架来实现功能,通常的做法是使用hive等工具辅助完成.但是对于其底层MR的原理还是有必要做一些了解. 2.MR客户端程序实现套路 这一小节总结归纳编写mr客户端程序 ...

  5. RAP开发入门-运行过程简析(三)

    今天通过标准的RAP程序来简单分析下RAP的启动过程 1.新建一个标准的rap plugin-in 项目: 得到的项目结构大概如下: run confi..->..add bundle(配置好b ...

  6. iOS7程序后台运行

    介绍 这次 iOS7 对程序后台运行进行了加强,但是仅仅是加强而已,要想像 Android 程序那样自由当然就别想了,苹果这么做主要还是出于电池使用时间考虑,但是这次的加强对大部分程序基本够用. 在介 ...

  7. Flink源码阅读(一)——Flink on Yarn的Per-job模式源码简析

    一.前言 个人感觉学习Flink其实最不应该错过的博文是Flink社区的博文系列,里面的文章是不会让人失望的.强烈安利:https://ververica.cn/developers-resource ...

  8. Eclipse Debug模式的开启与关闭问题简析_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 默认情况下,eclipse中右键debug,当运行到设置的断点时会自动跳到debug模式下.但由于我的eclipse环境 ...

  9. 3 weekend110的job提交的逻辑及YARN框架的技术机制 + MR程序的几种提交运行模式

    途径1: 途径2: 途径3: 成功! 由此,可以好好比较下,途径1和途径2 和途径3 的区别. 现在,来玩玩weekend110的joba提交的逻辑之源码跟踪 原来如此,weekend110的job提 ...

随机推荐

  1. OSG3.40 编译时,无法打开输入文件“optimized.lib”

    解决方案: 正常情况下,下图中会多出一项:ZLIB_LIBRARY_RELEASE,之后屡次编译,都提示"无法打开输入文件"optimized.lib"" 因为 ...

  2. 「坐上时光机,查找编译压缩后的文件最初的样子」gulp-sourcemaps 使用说明

    一般我们调试的 js/css 文件都是编译压缩后的,一旦出错很难定位原始的位置,gulp-sourcemaps 的出现帮助我们解决了这个问题. 首先我们看下目录结构: css js a.js b.js ...

  3. python 抽象类、抽象方法、接口、依赖注入、SOLIP

    1.程序设计原则:SOLIP SOLIP设计原则 1.单一责任原则(SRP) 一个对象对只应该为一个元素负责 2.开放封闭原则(OCP) 对扩展开放,修改封闭 3.里氏替换原则(LSP) 可以使用任何 ...

  4. vs中使用git

    vs中使用git 一.概念 Git是一个强调速度的分布式版本控制软件和源代码管理系统(SCM,source code management).Git最初是由Linus Torvalds为内核开发而设计 ...

  5. 高通vuforia+Unity3D 制作ar app

    很简单就可以用Unity3D做出增强现实的一个小例子 新人第一次写博客,若出现错误望指正^_^ 需要下载de东西: unity3d 5.0 http://unity3d.com/get-unity   ...

  6. zookeeper原理解析-客户端与服务器端交互

    Zookeeper集群中server数量总是确定的,所以集群中的server交互采用比较可靠的bio长连接模型:不同于集群中sever间交互zookeeper客户端其实数量是未知的,为了提高zooke ...

  7. nginx服务器http重定向到https的正确写法

    http重定向到https使用了nginx的重定向命令.那么应该如何写重定向?之前老版本的nginx可能使用了以下类似的格式. rewrite ^/(.*)$ http://domain.com/$1 ...

  8. 10 Symbol

    Symbol 书中讲了2部分. Symbol() Symbol 属性值. 完全两种画风的东西. 1. Symbol 首先他是一种全新的值. 不属于以前的任何一种 ES6引入了一种新的原始数据类型Sym ...

  9. python模块(shelve,xml,configparser,hashlib,logging)

    1.1shelve模块 shelve 模块比pickle模块简单,只有一个open函数,返回类似字典对象,可读可写:key必须为字符串, 而值可以是python所支持的数据类型. shelve模块主要 ...

  10. java在线支付

    http://blog.csdn.net/lidew521/article/category/1437251