前言
最近学了王爽教授写的《汇编语言》,整理一下学习笔记。
3.1 DS和[address]
8086CPU中有一个寄存器DS,通常用来存放要访问数据的段地址;
“[···]”表示一个内存单元,“[···]”中的数字表示偏移地址,段地址在DS中。
前面学习mov指令我们知道可以用mov指令将数据送入到寄存器中,比如
mov ax,1
但是我们不能用类似的方法将数据移入段寄存器中,比如
mov ds,1000H
这条指令就是非法的。所以只能用一个寄存器来进行中转。即:
mov bx,1000H
mov ds, bx
字的传送
8086CPU是16位结构,所以一次性可以传输16位数据,即传送一个字,占两个内存单元(一个内存单元是一个字节);低地址存低位字节,高地址存高位字节。
如数据1123H,1122H在内存1000:0 - 3单元中是这样存储的:
数据段
我们可以将一组长度为N(N<=64KB)、地址连续、起始地址为16倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。
3.2 栈
栈(stack)又名堆栈,是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
说白了,栈就相当是一个存储空间,访问方式比较特别,类似于一个箱子,先放进箱子里的书在最下面,最后放进去的书在最上面,想要取走书,就要
先取最上面的书,然后一本一本往下取,也就是最先放进去的最后出来,最后放进去的最先出来。
CPU提供的栈机制
8086CPU提供入栈和出栈指令,最基本的两个是PUSH(入栈)和POP(出栈),其操作都是以字为单位进行的。如:
push ax 表示将寄存器ax中的数据送入栈中;
pop ax 表示从栈顶取出数据送入ax。
3.3 SS和SP
上一章的学习我们知道,CS,IP中放着当前指令的段地址和偏移地址,显然也应该有相应的寄存器存放栈顶的地址。
8086CPU中,寄存器SS和PS分别用于存放栈顶的段地址和偏移地址。任意时刻,SS: PS指向栈顶元素。以push ax 的执行为例,由以下两步完成:
(1)SP=SP-2,SS: SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;
(2)将ax 中的内容送入 SS: SP指向的内存单元处,SS: SP此时指向新栈顶。
当栈空时,SS: SP指向栈空间最高地址单元的下一个单元。
3.4 栈顶超界问题
我们用SS和SP可以保证入栈出栈时找到栈顶,但我们如何保证入栈、出栈时栈顶不会超过栈空间?
这个问题可能需要自己来操心了,因为8086CPU只知道执行当前的指令,不会去考虑那么多,如果一旦发生了栈顶超界问题,那么栈外的数据就会被新数据覆盖,如果这段栈外空间存放的数据很重要的话,后果可想而知。
3.5 push、pop指令
上面我们提到过push、pop指令,这里我们在详细说一下;
push、pop的指令可以有以下形式:
push 寄存器/段寄存器/内存单元;将一个寄存器/段寄存器/内存单元中的数据入栈。
pop 寄存器/段寄存器/内存单元;出栈,用一个寄存器/段寄存器/内存单元接受出栈的数据。
我们要清楚的是,mov指令是一步操作,而push、pop指令是两步操作。执行push指令时,先改变SP,后向SS: SP处传送。执行pop指令时。先读取SS: SP处的数据,后改变SP。
注意,push、pop指令修改的只是SP。也就是说,栈顶的变化范围最大为:0 - FFFFH。
3.6 栈段
类比数据段,长度为N(N<=64KB)的一组地址连续、起始地址为16倍数的内存单元,当作栈来用,以栈的方式进行访问,从而定义了一个栈段。
对于数据段,段地址在DS中;
对于代码段,段地址在CS中;
对于栈段,段地址在SS中;
可见,CPU将内存中的某段内容当作代码,是因为CS: IP指向了那里;CPU将某段内存当作栈,是因为SS: SP指向了那里。
总结
以上为本人学习汇编语言时的摘录总结,主要内容来源于汇编语言(第四版) 王爽 著,大家若是感兴趣可以看看原书,很值得推荐,以上内容如果有什么错误的话,还请大家指正!