Linux内核分析实验一
Posted YoungX0701
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux内核分析实验一相关的知识,希望对你有一定的参考价值。
刘旸
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
基础知识:
1. 冯.诺依曼体系结构是现代计算机的基础,其核心为程序存储顺序执行,把程序本身当作数据来对待,程序和该程序处理的数据用同样的方式存储,并确定了存储程序计算机的五大组成部分和基本工作方法。
2.栈是一种运算受限的线性表,其限制是仅允许在表的一端进行插入和删除运算,即先进后出原则。
实验过程:
测试代码如下:
int g(int x)
return x + 1008;
int f(int x)
return g(x);
int main(void)
return f(71) + 1992;
使用命令 gcc –S –o test.stest.c –m32 将该C文件编译成汇编代码
精简后的汇编文件如下图所示:
下面我们开始分析汇编代码:
首先找到程序的入口,即main函数,然后开始逐条分析。
栈的初始状态:
(1)pushl %ebp
将ebp中的值压入栈中,同时esp向下移4个字节,即指向下一个地址的位置。
(2)movl %esp, %ebp
将esp中的值赋给ebp,即让ebp也向下移4个字节,此时ebp与esp指向了同一个位置。
(3)subl $4, %esp
将esp向下移动4个字节。
(1)~(3)构成了main函数的开栈的过程。
(4)movl $71, (%esp)
将esp指向的地址的内容加上71,即参数的值。
(5)call f
调用f函数,即保存此指令的下一条指令,并且跳转到f函数入口。
(6)pushl %ebp
movl %esp, %ebp
subl $4,%esp
f函数的开栈过程,可以看到,与main函数的类似。其实,每个函数的开栈都是这样的过程,所以以后只要看到这三句就基本可以判定是调用了函数在开栈的过程。
movl 8(%ebp),%eax
movl %eax,(%esp)
将参数传递过来。
(7)call g
调用g函数
(8)pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
g函数的开栈过程与参数传递。
addl $1008, %eax
做加法,将现在eax的值加上了1008,即eax=71+1008=1079。
(9)popl %ebp
g函数完成了该做的功能,开始退栈,先将ebp指回其父函数(f函数)的ebp的位置。
(10)ret
ret指令就是pop %eip,将程序的执行交还给父函数(f函数)。
(11)leave
leave指令就是movl %ebp, %esp + popl ebp,结果还是将ebp指回其父函数(main函数)的ebp的位置。
(12)ret
将程序的执行交还给父函数(main函数)。
(13)addl $1992, %eax
main函数继续进行加法,这次eax=1992+1079=3071。
(14)leave
ret
main函数退出,这个程序执行完毕,最终结果为3071,保存在eax中。
好啦,实验到这里就结束啦,充分展现了函数调用时开栈和退栈的过程!
以上是关于Linux内核分析实验一的主要内容,如果未能解决你的问题,请参考以下文章