How the Computer Works (based on X86/Linux)

注明

李振业
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000


一、实验过程


首先创建一个C语言文件


vi main.c


接着编写一段C语言代码



int g(int x)
{
  return x + 32;
}

int f(int x)
{
  return g(x);
}

int main(void)
{
  return f(6) + 1;
}


结束保存并退出



shift+:
wq


利用gcc的功能,将上面的代码编译成32位的汇编代码



gcc -S -o main.s main.c -m32


这样就将main.c编译成main.s文件,如下图


技术分享

技术分享

技术分享

技术分享

技术分享

技术分享


bwlq分别代表8位、16位、32位和64位,而这里的指令是以l结尾,说明该文件内容的确是32位的汇编代码。
将所有以点开头的内容删除,留下来的就是纯汇编代码。

技术分享技术分享

二、汇编分析

分析前先顺便明白以下知识:
1. EIP:Instruction Pointer 是如同指针一样指向内存的某一块区域,E开头则是因为为32位的系统
2. 堆栈是计算机中非常基础性的东西
3. CPU在实际取指令时根据CS:eip来准确定位一个指令
4. 寄存器模式,以%开头的寄存器标示符
5. 立即数是以$开头的寄存器标志符
6. 直接寻址:直接访问一个指定的内存地址的数据
7. 间接寻址:将寄存器的值作为一个内存地址来访问内存
8. 变址寻址:在间接寻址的时候改变寄存器的数值
9. Linux内核使用的是AT&T汇编格式
10.eip寄存器不能被直接修改,只能通过特殊指令间接修改
11.函数调用堆栈是由逻辑上多个堆栈叠加起来的
12.函数的返回值默认使用eax寄存器储存返回给上一级函数


设执行前的栈如图所示,esp与ebp均为0

 

 



从代码里的行数分析:

18-19:(main开始) 入栈 一 = ebp0,esp下移0→1,ebp下移0→1

20:esp下移1→2

21:二 = 6

22:三 = eip(23),esp下移2→3,eip跳转到f(第8行)

9-10:入栈 四 = ebp1,esp下移3→4,ebp下移1→4

11:esp下移4→5

12:变址寻址,eax = 6

13:五=6

14:六=eip(15),esp下移5→6,eip跳转到g(第1行)

2-3:入栈 七=ebp4,esp下移6→7,ebp下移4→7

4:变址寻址,eax=6

5:eax=eax+32=38

6:出栈 ebp上移7→4,esp上移7→6

7:esp上移6→5,eip(15)

15:执行leave,esp上移5→4,ebp上移4→1,esp再上移4→3

16:esp上移3→2,eip(23)

23:eax=eax+1=39

24:执行leave,esp上移2→1,ebp上移1→0,esp再上移1→0

25:ret,结束

可看出栈的执行情况如下,最后经过了从入栈到出栈的过程,eax的值为39

一 = ebp0

二 = 6

三 = eip(23)

四 = ebp1

五 = 6

六 = eip(15)

七 = ebp4

 


三、总结

没学过汇编和操作系统原理直接学Linux内核分析的确比较吃力,还好坚持下来和做完作业与测试。
希望能再接再厉,继续深入了解。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。