本文已参与「新人创作礼」活动,一起开启掘金创作之路。 3.8栈顶越界的问题
溢出攻击
当栈满的时候再使用push指令入栈
栈空的时候再使用pop指令出栈
栈顶越界是危险的
8086CPU不保证对栈的操作不会超界
8086CPU的工作机理,只考虑当前的情况:
当前栈顶在何处;
当前要执行的指令是哪一条;
push、pop指令格式
段寄存器是以s结尾
通用寄存器以x结尾
各类段寄存器的存储内容
数据的段地址永远从ds中获得
代码的段地址永远从cs中获得
栈的段地址永远从ss中获得
问题3.7
问题3.8
xor ax,ax 异或置零
问题3.9
问题3.10(错题)
mov ax,1000H
mov ss,ax
mov sp,2 (push时栈顶偏移位置先会减2,详见3.6push指令的执行过程)
mov ax,2266H
push ax
mov sp,2
结论
push、pop实质上就是一种内存传送指令,可以在寄存器和内存之间传送数据,与mov指令不同的是,push和pop指令访问的内存单元的地址不是在指令中给出的,而是由SS:SP指出的。
同时,push和pop指令还要改变SP中的内容。
CPU执行mov指令只需一步操作,就是传送,而执行push、pop则需要两步操作
执行push时:
先改变SP,后向SS:SP处传送。
执行pop时:
先读取SS:SP处的数据,后改变SP。
ATTENTION
由于pop、push修改的只是SP。SP是偏移地址,范围0FFFFH。所以说栈顶的变化范围最大为:0FFFFH。
0~64KB
(16位的CPU)
任何时刻,SS:SP指向栈顶元素
8086CPU只记录栈顶,栈空间的大小我们要自己管理
用栈可以暂存以后需要恢复的寄存器的内容
3.10栈段
将一组地址连续、起始地址为16的倍数的内存单元,当作栈来用,从而定义了一个栈段。
问题3.11(新)存疑
理论上SS:SP应指向1FFFFH+1=20000H,此时SP=10000H??
栈空时,SS:SP指向20000H, SP:10000H->0000H???
压栈到栈满,SS:SP指向10000H SP:0000H又变回0,如果再次压栈,栈顶将环绕,覆盖原来栈中的内容
0000H?
扩展
早期的堆栈主要用来保存返回地址(函数的返回地址)
eg:C语言A函数调用B函数,main函数运行,main函数结尾,中间调用的各种函数都需要返回,如要调用A函数时,需将现有寄存器中的数据保存,存放于栈中,栈用来临时存放东西。调用完ret回来后,通过栈直接恢复,避免数据的流失或覆盖,(栈为了函数而存在?)面对过程的存在而存在。
段的综述
一段内存可以同时拥有三种段身份
检测点3.2
mov ax,2000H
mov ss,ax
mov sp,10h
(2)出错
mov ax,1000H
mov ss,ax
mov sp,0
该题将20000H作为数据段
故10000H作为栈段
将栈段数据pop出
逆序pop [E]可知应将栈顶元素10000H pop出存入 数据段尾2000FH
此时栈满 SS:SP指向10000H
pop先读内容后移动指针