署名信息

郭春阳 原创作品转载请注明出处 :《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. 单片机TM4C123学习(八):SPI接口D/A

    1.头文件和变量定义(不是很清楚) #include "driverlib/ssi.h" #include "driverlib/i2c.h" #include ...

  2. good excel website

    http://www.codematic.net/excel-tools/free-excel-tools.htm

  3. ObjC.class-cluster

    class cluster In a class cluster, only an abstract superclass is public. Allocating an instance actu ...

  4. three.js 源码注释(三十九)Light/HemisphereLight.js 半球光、 自然光(天光效果)

    /*** * HemisphereLight类 是在场景中创建半球光,就是天光效果,经常用在室外,将各个位置的物体都照亮,室内的光线大多是方向性的, * 无论是窗口还是灯槽,用平面光很方便,室外用平面 ...

  5. Win7中不能调试windows service

    多年前玩过一次windows service,觉得挺简单的. 这次工作要维护产品中的windows service,发现不是那么简单,vs附加调试器的窗体中无法找到windows service进程. ...

  6. php匹配中文代码(字符串中包含中文或者全是中文)

    <?php$str= "中文";//全部是汉字的$par = "\x80-\xff";$par2= chr(0xa1).'-'.chr(0xff);//包 ...

  7. live555 直播arm-linux视频

    live555例程testOnDemandRTSPServer.cpp启动一个流服务器 首先启动使用环境, TaskScheduler* scheduler = BasicTaskScheduler: ...

  8. ADB 常用命令总结(持续更新)

    1.adb devices 2.抓取adb log:adb logcat -v time >test.log  (Log直接保存在个人电脑用户名下) 3.adb install 包地址(可以直接 ...

  9. 【java】:生成excel

    //生成报表公用方法 //excelName: 生成的文件名 //list:时间/日期/描述 //listSelectFiled:  标题 //showContent :  文件内容bean //生成 ...

  10. 【转】 全世界最短的IE判定

    以前最短的IE判定借助于IE不支持垂直制表符的特性搞出来的. var ie = !+"\v1"; 仅仅需要7bytes!讲述外国人是如何把IE的判定从32 bytes一步步缩简成7 ...