分析一个C语言程序生成的汇编代码-《Linux内核分析》Week1作业
署名信息
郭春阳 原创作品转载请注明出处 :《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作业的更多相关文章
- Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程
Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...
- linux内核分析综合总结
linux内核分析综合总结 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核分析 ...
- Linux内核分析(七)----并发与竞态
原文:Linux内核分析(七)----并发与竞态 Linux内核分析(七) 这两天家里的事好多,我们今天继续接着上一次的内容学习,上次我们完善了字符设备控制方法,并深入分析了系统调用的实质,今天我们主 ...
- Linux内核分析(五)----字符设备驱动实现
原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷, ...
- 简单C程序生成的汇编代码分析
首先给出完整的C代码: int g(int x) { ; } int f(int x) { return g(x); } int main(void) { )+; } 使用命令:gcc –S –o h ...
- 《linux内核分析》作业一:分析汇编代码
通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的(王海宁) 姓名:王海宁 学号:20135103 课程:<Linux内核分析& ...
- linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作
一.实验 使用gcc –S –o main.s main.c -m32 命令编译成汇编代码,如下代码中的数字请自行修改以防与他人雷同 int g(int x) { return x + 3; } in ...
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- Linux内核分析—完成一个简单的时间片轮转多道程序内核代码
---恢复内容开始--- 20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10 ...
随机推荐
- DNS劫持和DNS污染的区别
我们知道,某些网络运营商为了某些目的,对DNS进行了某些操作,导致使用ISP的正常上网设置无法通过域名取得正确的IP地址.常用的手段有:DNS劫持和DNS污染. 什么是DNS劫持 DNS劫持就是通过劫 ...
- PHP 四种基本排序算法的代码实现
前提:分别用冒泡排序法,快速排序法,选择排序法,插入排序法将下面数组中的值按照从小到大的顺序进行排序. $arr(1,43,54,62,21,66,32,78,36,76,39); 1. 冒泡排序 思 ...
- unity3d使用脚本保存屏幕截图
using UnityEngine; using System.Collections; using System.IO; public class FrameAnimation : MonoBeha ...
- 第五章 springboot + mybatis
springboot集成了springJDBC与JPA,但是没有集成mybatis,所以想要使用mybatis就要自己去集成.集成方式相当简单. 1.项目结构 2.pom.xml <!-- 与数 ...
- [转载] 散列表(Hash Table)从理论到实用(中)
转载自:白话算法(6) 散列表(Hash Table)从理论到实用(中) 不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好 ...
- 基本数据类型范围大小&&字节大小
char -128 ~ +127 short -32767 ~ + 32768 unsigned short 0 ~ 65536 int -2147483648 ~ +2147483647 unsig ...
- php错误级别的设置方法
PHP在运行时, 针对严重程度不同的错误,会给以不同的提示. eg:在$a没声明时,直接相加,值为NULL,相加时当成0来算.但是,却提示NOTICE,即注意. 我们在开发中, 为了程序的规范性,把报 ...
- VMware vSphere 5.1 简介与安装
虚拟化系列-VMware vSphere 5.1 简介与安装 标签: 虚拟化 esxi5.1 VMware vSphere 5.1 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 . ...
- android中 EditTex t的 inputType 属性
//文本类型,多为大写.小写和数字符号 android:inputType="none" android:inputType="text" a ...
- sscanf函数用法详解
sscanf() - 从一个字符串中读进与指定格式相符的数据. 函数原型: Int sscanf( string str, string fmt, mixed var1, mixed var2 ... ...