首页 > 代码库 > “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.输入下面的指令编译成汇编代码:

  1. 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内核分析”实验一