分析一个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 ...
随机推荐
- Light OJ 1019 - Brush (V)(图论-dijkstra)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1019 题目大意:Tanvir想从节点1的位置走到节点n的位置, 输出最短距离, ...
- protocol buffers的使用示例[z]
[http://blog.csdn.net/zhu_xun/article/details/19397081] protocol buffers的使用示例 如果不了解protocol buffers, ...
- 使用 IntraWeb (42) - 测试读取 SqLite (一)
为通过 FireDAC(XE5开始支持的) 使用 SqLite, 现在已换成 XE6 + IntraWeb v14.0.32 Ultimate. 首先把官方提供的 C:\Users\Public\Do ...
- hadoop2.0单机安装
hadoop发行的版本:apache hadoop;HDP;CDH -----这里只使用apache hadoop---可以在网站hadoop.apache.org网站上找到 hadoop安装方式:自 ...
- framebuff 显示子系统
#include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <linux/fb.h ...
- 云计算和大数据时代网络技术揭秘(十七)VOQ机制
VOQ机制 本章介绍的VOQ是一种新型的QoS机制,目的是为了解决著名的交换机HoL难题. 但VOQ强烈依赖于调度算法,例如,一个48口的交换机,每个端口都要维护48-1个FIFO缓存队列, 一共48 ...
- treeMap and treeSet
TreeSet:如果要对对象进行排序,对象类要实现Comparable接口! TreeMap:如果要对对象进行排序,对象类要实现Comparable接口! 下面是我自己写的小程序主要传输对象 publ ...
- JS初级-作用域
作用域:域:空间.范围.区域--作用:读.写 script 全局变量.全局函数 自上而下 函数 由里到外 {} 浏览器 ...
- 黑马程序员_Java基础:十进制转换其他进制
------- android培训.java培训.期待与您交流! ---------- 平时使用中,进制转换只要使用Integer这个包装类中的方法即可完成. 但其实我们也能用自己的方法去实现,这有助 ...
- WPF 虚拟键盘
之前做了一款WPF虚拟键盘,调用Win32的API,可以模拟键盘事件. 现将代码分享如下: 按键布局如下: <Button Name="> <StackPanel Orie ...