栈
定义:是一种用来存储函数调用时的临时信息的结构,如函数调用所传递的参数、函数的返回地址、函数的局部变量等
特性:先进后出(FILO)
基本操作:
- PUSH:压栈
- POP:弹栈
函数调用对栈的操作
- 把指令寄存器EIP(指向当前CPU将要运行的下一条指令的地址)入栈,作为程序的返回地址(一般用RET)表示
- 把基址寄存器EBP入栈(保护数据)
- 把EBP设为栈顶指针ESP,作为新的基地址
- 动态存储分配留出一定空间,即把ESP减去一个适当的值
获取参数值
call指令执行完毕的栈布局:
为了得到参数2,我们使用EBP保存ESP,而为了保护保存ESP的EBP,我们将其入栈,得到如此结构:
获取局部变量值
栈分布如图:
获取返回值
函数返回值通过eax寄存器传递,如果两个返回值还会使用edx:
如果返回值太大、就需要主调函数在call被调函数之前创建临时空间:
然后,在被调函数传递返回值时:
- 通过[EBP+偏移]获得返回值的存放地址
- 把返回值写入到这个内存
- 把返回值写入到EAX,
mov eax,[ebp+偏移]
函数调用的扫尾工作
- 平衡栈,清除参数传递消耗的栈空间
- 只需要改变esp值就可
- 可以由调用函数使用
ret 参数占用栈大小
来清除
栈溢出
例如程序:
1 |
|
当我们输入的数据大于16个字节时就会产生栈溢出,此时输入的字节会覆盖栈底内容导致出错,这就是栈溢出
例题
- 关于函数,下列说法不正确的是( )
A. 被调函数通过EBP+偏移访问主调函数传递的参数
B. 被调函数返回后,主调函数不需要再进行清栈的动作
C. 被调函数通过寄存器将返回值或返回值地址传递给主调函数
D. 被调函数通过EBP-偏移访问自己的局部变量
参考答案:B
解析:主调函数是否进行清栈是根据被调函数是否清栈来的,而不是一定不清栈