寄存器(内存访问)2

181 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 3.8栈顶越界的问题

溢出攻击

当栈满的时候再使用push指令入栈

image.png

栈空的时候再使用pop指令出栈

image.png 栈顶越界是危险的

image.png 8086CPU不保证对栈的操作不会超界

image.png 8086CPU的工作机理,只考虑当前的情况:

当前栈顶在何处;

当前要执行的指令是哪一条;

push、pop指令格式

image.png 段寄存器是以s结尾

通用寄存器以x结尾

image.png  

image.png 各类段寄存器的存储内容

数据的段地址永远从ds中获得

代码的段地址永远从cs中获得

栈的段地址永远从ss中获得

问题3.7

image.png

image.png 问题3.8

image.png

image.png  

xor ax,ax 异或置零

问题3.9

image.png

image.png

问题3.10(错题)

image.png

mov ax,1000H
mov ss,ax
mov sp,2  (push时栈顶偏移位置先会减2,详见3.6push指令的执行过程)
mov ax,2266H
push ax

mov sp,2

image.png

image.png

结论

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(新)存疑

image.png

理论上SS:SP应指向1FFFFH+1=20000H,此时SP=10000H??

image.png

栈空时,SS:SP指向20000H, SP:10000H->0000H???

压栈到栈满,SS:SP指向10000H SP:0000H又变回0,如果再次压栈,栈顶将环绕,覆盖原来栈中的内容

0000H?

扩展

早期的堆栈主要用来保存返回地址(函数的返回地址)

eg:C语言A函数调用B函数,main函数运行,main函数结尾,中间调用的各种函数都需要返回,如要调用A函数时,需将现有寄存器中的数据保存,存放于栈中,栈用来临时存放东西。调用完ret回来后,通过栈直接恢复,避免数据的流失或覆盖,(栈为了函数而存在?)面对过程的存在而存在。

 

段的综述

image.png

image.png

一段内存可以同时拥有三种段身份

 

检测点3.2

image.png

mov ax,2000H 
mov ss,ax    
mov sp,10h   

(2)出错

image.png

mov ax,1000H
mov ss,ax   
mov sp,0    

该题将20000H作为数据段

故10000H作为栈段

将栈段数据pop出

逆序pop [E]可知应将栈顶元素10000H pop出存入 数据段尾2000FH

此时栈满 SS:SP指向10000H

pop先读内容后移动指针