若余相思 发表于 2017-7-17 15:23:45

《汇编语言》第三章3.6节~3.10节

3.6节 栈
栈和C语言中的数组一样也是一种数据的存储方式
如下图

栈有栈顶和栈低,箭头所指向的软件工程这本书的这个内存地址为栈顶,框架下面便是栈低。
栈有两种操作:入栈(又称压栈)和出栈,他们的指令分别是push和pop
栈的特点:后进先出(LIFO)

3.7节 CPU提供的栈机制
栈的入栈和出栈操作都是以字位单位,栈由栈顶指针指向栈顶
和CS:IP指向CPU在任意时刻操的物理地址一样也有SS:SP指向栈在任意时刻的操作的物理地址(顺便在这里复习一下ds表示数据段寄存器存放偏移地址要操作的段地址)
SS表示栈段寄存器,是存放段地址。SP是存放SS的偏移地址。
如下图为入栈内存情况:

该图为物理地址为10000H~1000FH的栈段
1、为栈的空栈的状态,此时栈顶指针在物理地址为10010H的地方(图中并没有画出箭头指向栈顶)
2、为栈顶指针减2(因为一个字为2个字节)到达1000EH的地方此时执行入栈push ax
指导图4,push cx此时内存时的情况

如下图为出栈内存情况:

出栈主要为先图5执行pop ax,那么 ax = 1122H 此时ax的值等于了入栈时cx的值了,然后栈顶指针会加2,指导图7出栈完成,此时栈变为空栈,栈顶指针指向10010H处。

从上面可以总结出来得知:
入栈:
(1)SP = SP - 2,SS:SP指向新的栈顶单元
(2)执行入栈操作,比如上图2,会将ax的值送入SS;SP指向的内存单元。

出栈:
(1)会先执行出栈先,如上图5,pop ax,让ax = 1122H
(2)然后再SP = SP + 2 ,这时才让栈顶指针指向新的栈顶

3.8节 栈顶超界问题
入栈和出栈操作会出现溢出栈段的问题,即超界问题
push 入栈超界如下图:

如图所示,在图1栈段为在10010H~1001FH的范围内,图2执行8次push ax之后,图3在执行push ax之后栈顶将超出栈的空间

pop出栈超界如下图:

这段栈空间中,图2执行了8次pop ax操作后,在图3再执行pop ax 之后的状态,栈顶超出栈的空间。

栈顶越界是危险的,因为超过栈空间后,在栈之外的空间可能存放这其他程序的指令和数据,但我们在入栈出栈不小心将这些数据改写将引发一连串的错误。

3.9节 push、pop指令
push 寄存器
pop 寄存器
可以将寄存器的数据入栈,也可以将出栈的数据放在寄存器

push 段寄存器
pop 段寄存器
可以将段寄存器的数据入栈,也可以将出栈的数据放在段寄存器

push 内存单元
pop 内存单元
可以将内存单元的数据入栈,也可以将出栈的数据放在内存单元

3.10节 栈段
我们可以将长度为N(N<=64KB)的一组地址连续的,起始地址为16的倍数的内存单元,当作栈空间来使用,从而定义了一个栈段


段的总结:
到目前为止,我们学习了“代码段”、“数据段”、”栈段“
对于代码段:我们将段地址放在CS中,偏移地址放在IP中,这样CPU将执行我们定义断码段这个指令
对于数据段:我们将段地址放在DS中,在使用内存单元的数据时,使用【address】当作偏移地址,当我们要使用这段数据时,CPU将自动的使用ds的段地址
对于栈段:我们将段地址放在CS中,偏移地址放在SP中,这样CPU在需要栈执行的时候,比如push、pop指令等,就将我们定义的栈段当作栈空间来使用。

无论我们如何安排,CPU执行的是CS:IP所指向的那里的指令。DS和SS都只是辅助CPU方便的执行或取来某些数据而设立的寄存器。
代码段、数据段和栈段可以在同一个内存空间。

总结:
(1)是一种数据的存储方式
(2)入栈push和出栈pop
(3)push指令的步骤1、SP = SP - 2   
                                   2、向SS:SP指向的字单元送入数据

       pop指令的步骤 1、从SS:SP指向的字单元读取数据
                                  2、SP = SP + 2
(4)在任意时刻,SS:SP指令栈顶元素
(5)push和pop只是内存传送指令,注意灵活运用
页: [1]
查看完整版本: 《汇编语言》第三章3.6节~3.10节