基于孟宁老师的Linux内核分析
1 int g(int x){ 2 int y = x + 3;3 return y;4 }5 6 int f(int x){7 int z = x + 10;8 return g(z);9 }10 11 int main(){12 int a = f(8) + 1;13 return 0;14 }
对于上述源代码,我们尝试对其进行分析,先编译gcc -g -o lab1 lab1.c
(注意计算机系统是32位Linux)。
堆栈能够干什么
对于C语言来说,32位下,堆栈都能干什么?
- 函数调用,使用call的时候,保存当前EIP的值,然后函数指向完,ret再返回来。
call指令,能够让EIP入栈,ret指令让EIP出栈 - 保存函数局部变量,函数内的局部变量,就是保存在当前函数的栈空间中。
- 传递函数参数,参数先被放入栈空间中,然后再执行call指令调用函数(对于32位系统,从右到左依次压栈),因此来说,函数参数一定是被调用的函数的栈空间上面的(高地址)
另外,函数的返回值,会被保存到EAX中,可能是值,也可能是地址(如果是地址,地址对应的空间就不能是会被销毁的栈空间,需要是堆空间,或者是暂时不会被销毁的栈空间)。
指针和引用也可以传递返回值,他们是作为参数传过来的,修改指针指向地址的值,就相当于是传参了。
关于栈空间的构建与撤销,其实就两个重要节点
- 栈底保存EBP的值,ESP作为栈顶,就是栈空间的创建
- 栈空间创建后,随着函数对ESP的使用,栈空间会各种改变,但是可以一键还原会创建栈空间前的状态,因为EBP一直指向栈底之上的一个位置,先把ESP = EBP,然后把原来的EBP出栈,就达到了复原,这样一来,这个函数从栈空间来看,就像没有执行过一样。而栈空间也会被回收,不能再使用。
存储2个局部变量: