首页 > 代码库 > “Linux内核分析”实验一
“Linux内核分析”实验一
“Linux内核分析”实验一
作者:何振豪
原创作品转载请注明出处 http://www.cnblogs.com/scoyer/p/6411414.html
《Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000
计算机由硬件和软件组成,硬件主要是CPU和内存,软件是系统软件和应用软件。最开始的计算机是由冯诺依曼提出的存储程序的思路开始的,这就对应硬件的CPU和内存,CPU执行指令,指令和相关数据放在内存,CPU按照ecs::eip指示的地方取出指令执行,不断执行。操作系统主要的作用是提供接口,程序猿根据这些接口进行编程,形形色色的软件就这样产生了。Linux是一个非常优秀的操作系统,系统的代码是开源的,所以研究linux内核是了解计算机怎么工作的一个重要途径。Linux要面对的是怎么规划计算机硬件使得他们能够互相协作,一步一步执行相应的代码。
当前这个实验要求的是反汇编一个简单的c程序,直接阅读汇编代码对理解计算机硬件的核心工作机制(存储程序计算机和函数调用堆栈)有一定的帮助,下面就是我的实验过程。
实验环境:实验楼
1.建立一个c文件exp.c
exp.c代码如下:
2.输入下面的指令编译成汇编代码:
- gcc –S –o exp.s exp.c -m32
3.开始得到的代码很多系统参数代码,删掉所有开头带.的代码,得到如下代码:
对上述汇编代码进行简单分析如下,假设一开始的堆栈状态如下:
|
0 |
|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
假设一开始的esp = ebp = 0,我们都知道c语言的执行函数是main,所以从第19行开始执行,逐行解释如下:
(1)将ebp入栈,这时候的esp-4即变成图中标号为1的位置esp=1,然后把ebp推入栈即[0] = ebp 0;
(2)ebp = esp = 1
(3)esp=2
(4)[1] = 10
(5)提到f函数去执行,这时候执行的call指令包含两条,一是将当前的eip保存到栈中,所以esp=3,[2] = eip 24(表示当前执行指令的行号);二是将eip设置为f函数的第一条指令,所以eip被修改为第九行的地址,所以下面执行的指令是第九行开始
(6)esp = 4,[3] = ebp 1
(7)esp = ebp = 4
(8)esp = 5
(9)eax = (ebp + 8) = [1] = 10(传给f函数的值)
(10)eax = 10 + 11 = 21
(11)[4] = 21
(12)执行call指令按照上面叙述的两步进行得到:esp = 6, [5] = eip 16, eip = 2,所以下面的指令从第二行开始
(13)esp = 7, [6] = ebp 4
(14)esp = ebp = 7
(15)eax = 21
(16)eax = 12 + 21 = 33
(17)ebp = [6] = 4, esp = 6
(18)ret命令即pop %eip,所以现在是eip = [5] = 16, esp = 5调回到第16行开始执行
(19)leave也是包含两条指令,esp = ebp = 4,ebp = [3] = 1,esp = 3
(20)eip = 24, esp = 2调回到24行开始执行
(21)eax = 34
(22)esp = ebp = 1,ebp = 0, esp = 0
从硬件的角度来看,通过不断入栈和出栈进行函数的调用,用一个栈存储上次执行的位置和eax寄存器存储传给函数的参数和函数返回的参数,计算机就是通过CPU不断执行相应指令,利用存储程序的特点一步一步工作的。
“Linux内核分析”实验一