署名信息

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

C源码

这里为了防止重复,修改了部分源码

int g(int x)
{
return x + 99;
} int f(int x)
{
return g(x);
} int main(void)
{
return f(22) + 36;
}

运行 gcc -S -o foo.s -m32 foo.c后,生成的汇编代码为:

g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $99, %eax
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
pushl 8(%ebp)
call g
addl $4, %esp
leave
ret
main:
pushl %ebp
movl %esp, %ebp
pushl $22
call f
addl $4, %esp
addl $36, %eax
leave
ret

分析代码运行过程

首先进入main函数:

`pushl	 %ebp, movl %esp, %ebp`两行代码,将ebp压入栈,
然后esp的值赋给ebp,这里esp的值先减4,ebp指向与esp相同的位置
以上指令相当于enter,进入了一个新的函数调用栈
将22压入栈(这里其实是定义接下来调用的f的形参int x,并赋值)
调用f,这里先保存eip(PC计数器)的值入栈,esp的值-4,然后将f的地址赋给eip

进入f函数:

执行enter的两条指令,进入新的函数调用栈(同上)
将ebp向前8个字节位置的值(main中压栈的22)压栈,esp-4
这里是定义g的形参并赋值
调用g,eip先压栈,然后eip变为g的地址

进入g函数:

首先执行enter的两条指令,进入新的调用栈(同上)
`movl 8(%ebp), %eax` 首先寻址,将f中压栈的数(也就是g的形参x),赋给eax
`addl $99, %eax` eax中得值+99,对应C语句 x + 99
`popl %ebp` 这里因为g中没有开辟新的栈空间(esp的值没有变化),所以这句和leave语句等价
执行完,这一句,ebp恢复到之前的值(f中得状态)
执行ret,其实是执行popl eip,将栈中保存的eip的值,赋给eip
此时ebp、esp和eip均恢复到调用f中得状态
退出g,返回值保存在eax中

回到f函数:

`addl    $4, %esp`  esp+4,因为前面进行了pushl开辟新的变量,所以这里需要丢弃栈顶
之后执行leave 和 ret,恢复esp、ebp、eip的值,同上
f仅仅返回g的返回值,这里不改动eax,里面保存着g的返回值

回到main函数:

`addl    $4, %esp`丢弃栈顶,原因是上面进行push,定义了新的变量
` addl $36, %eax` f(22)的返回值+36,相当于C中得 f(22) + 36
main函数leave ret 返回上一层
gcc中应该为__libc_start_main,它可以接收到main的返回值,在eax中

注意点

1.C中的函数,是先定义形参并赋值,然后才进入该函数代码
2.函数调用中占用的栈空间,不仅仅包括局部变量,还包括22这种常量
3.每次函数调用,都执行enter,这条指令的效果相当于开辟了一个新的空栈
4.call调用函数时,eip保存的是call的下一条指令

博客截图

实验环境是在Ubuntu 14.10 32bit,在mac OS X上远程登录

对计算机工作流程的认识

图灵机可以执行某些特定操作
通用图灵机可以执行传给它的指令
现在计算机采用冯诺依曼体系结构,将程序和数据均存储在内存中,只需要程序员编写计算机可以识别的代码即可,计算机会将这些代码编译为可执行的指令。

分析一个C语言程序生成的汇编代码-《Linux内核分析》Week1作业的更多相关文章

  1. Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程

    Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...

  2. linux内核分析综合总结

    linux内核分析综合总结 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核分析 ...

  3. Linux内核分析(七)----并发与竞态

    原文:Linux内核分析(七)----并发与竞态 Linux内核分析(七) 这两天家里的事好多,我们今天继续接着上一次的内容学习,上次我们完善了字符设备控制方法,并深入分析了系统调用的实质,今天我们主 ...

  4. Linux内核分析(五)----字符设备驱动实现

    原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷, ...

  5. 简单C程序生成的汇编代码分析

    首先给出完整的C代码: int g(int x) { ; } int f(int x) { return g(x); } int main(void) { )+; } 使用命令:gcc –S –o h ...

  6. 《linux内核分析》作业一:分析汇编代码

    通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的(王海宁) 姓名:王海宁                             学号:20135103 课程:<Linux内核分析& ...

  7. linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作

    一.实验 使用gcc –S –o main.s main.c -m32 命令编译成汇编代码,如下代码中的数字请自行修改以防与他人雷同 int g(int x) { return x + 3; } in ...

  8. linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...

  9. Linux内核分析—完成一个简单的时间片轮转多道程序内核代码

    ---恢复内容开始--- 20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10 ...

随机推荐

  1. DNS劫持和DNS污染的区别

    我们知道,某些网络运营商为了某些目的,对DNS进行了某些操作,导致使用ISP的正常上网设置无法通过域名取得正确的IP地址.常用的手段有:DNS劫持和DNS污染. 什么是DNS劫持 DNS劫持就是通过劫 ...

  2. PHP 四种基本排序算法的代码实现

    前提:分别用冒泡排序法,快速排序法,选择排序法,插入排序法将下面数组中的值按照从小到大的顺序进行排序. $arr(1,43,54,62,21,66,32,78,36,76,39); 1. 冒泡排序 思 ...

  3. unity3d使用脚本保存屏幕截图

    using UnityEngine; using System.Collections; using System.IO; public class FrameAnimation : MonoBeha ...

  4. 第五章 springboot + mybatis

    springboot集成了springJDBC与JPA,但是没有集成mybatis,所以想要使用mybatis就要自己去集成.集成方式相当简单. 1.项目结构 2.pom.xml <!-- 与数 ...

  5. [转载] 散列表(Hash Table)从理论到实用(中)

    转载自:白话算法(6) 散列表(Hash Table)从理论到实用(中) 不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好 ...

  6. 基本数据类型范围大小&&字节大小

    char -128 ~ +127 short -32767 ~ + 32768 unsigned short 0 ~ 65536 int -2147483648 ~ +2147483647 unsig ...

  7. php错误级别的设置方法

    PHP在运行时, 针对严重程度不同的错误,会给以不同的提示. eg:在$a没声明时,直接相加,值为NULL,相加时当成0来算.但是,却提示NOTICE,即注意. 我们在开发中, 为了程序的规范性,把报 ...

  8. VMware vSphere 5.1 简介与安装

    虚拟化系列-VMware vSphere 5.1 简介与安装  标签: 虚拟化 esxi5.1 VMware vSphere 5.1 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 . ...

  9. android中 EditTex t的 inputType 属性

    //文本类型,多为大写.小写和数字符号    android:inputType="none"    android:inputType="text"    a ...

  10. sscanf函数用法详解

    sscanf() - 从一个字符串中读进与指定格式相符的数据. 函数原型: Int sscanf( string str, string fmt, mixed var1, mixed var2 ... ...