《汇编语言》——王爽 第三章 寄存器 (内存访问)

这一章,我们从访问内存的角度继续学习几个寄存器

3.1内存中字的存储

小端字:这个字的低位字节存放在低地址单元中,高位字节存放在高地址单元中

3.2DS和[address]

[...]表示一个内存单元,[...]中的0表示内存单元的偏移地址。

8086CPU自动取ds中的数据为内存单元的段地址

8080CPU不支持将数据直接送入段寄存器的操作,ds是一个段寄存器,所以mov ds,1000H这条指令是非法的。那么如何将1000H送入ds呢?只好用一个寄存器来进行中转,即先将1000H送入一个一般的寄存器,如bx,再将bx中的内容送入ds。

3.3字的传送

3.4 mov,add,sub指令

3.5 数据段

3.1-3.5小结:

3.6栈

栈是一种具有特殊的访问方式的存储空间。

3.7CPU提供的栈机制

8086CPU的入栈和出栈都是以字为单位进行的。

一个重要的问题是:CPU如何知道10000H~1000FH这段空间被当作栈来使用?

必须要知道哪个单元是栈顶单元,可是,如何知道呢?

CPU如何知道当前要执行的指令所在的位置?我们现在知道答案,那就是CS,IP中存放着当前指令的段地址和偏移地址。现在的问题是:CPU如何知道栈顶的位置?显然,也应该存在相应的寄存器来存放栈顶的地址,8086CPU中,有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在SP中。任意时刻,SS:SP指向栈顶。

push ax的执行,由以下两步完成:(自动完成以下两步)
1.SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶

2.将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新的栈顶。

从图中,我们可以看出,8086CPU中,入栈时,栈顶从高地址向低地址方向增长。

注意:图3.12中,出栈后,SS:SP指向新的栈顶1000EH,pop操作前的栈顶元素,1000CH处的2266H依然存在,但是,它已不在栈中。当再执行push等入栈操作后,它将被覆盖。

3.8栈顶越界的问题

栈顶超界是危险的,因为我们既然将一段空间安排为栈,那么在栈空间之外的空间里很可能存放了具有其他用途的数据,代码等,这些数据,代码可能是我们自己程序中的,也可能是别的程序中的(毕竟一个计算机系统中并不是只有我们自己的程序在运行)。但是由于我们在入栈出栈时的不小心,而将这些数据,代码意外地改写,将会引发一连串的错误。

对于8086CPU并没有这样的寄存器(CPU在执行push指令的时候靠检测栈顶上限寄存器,在执行pop指令时靠检测栈底寄存器保证不会超界)

这也就是说,8086CPU只知道栈顶在何处,而不知道我们安排的栈空间有多大。

我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小。

3.9push,pop指令

一定要注意:它的执行过程是,先将记录栈顶偏移地址的SP寄存器中的内容减2,使得SS:SP指向新的栈顶单元,然后再将寄存器中的数据送入SS:SP指向的新的栈顶单元。

同时,push和pop指令还要改变SP中的内容(自动的)

我们要十分清楚的是,push和pop指令同mov指令不同,CPU执行mov指令只需一步操作,就是传送,而执行push,pop指令却需要两步操作。执行push时,CPU的两部操作是:先改变SP,后向SS:SP传入。

注意,push和pop等栈操作指令,修改的只是SP,也就是说,栈顶的变化范围最大为0~FFFFH。

栈是一种非常重要的机制,一定要深入理解,灵活掌握。

3.10栈段

段的综述:

我们可以将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内单元。这完全是我们自己的安排。

我们可以用一个段存放数据,将它的地址放在DS中,将它定义为“数据段”。用mov,add,sub等访问内存单元的指令时,CPU就将我们定义的数据段中的内容当作数据来访问。

我们可以用一个段存放代码,将它的段地址放在CS中,将它定义为“代码段”,将段中第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令。

我们可以用一个段当作栈,将它的段地址放在SS中,将它定义为“栈段”,将栈顶单元的偏移地址放在SP中。

一段内存,可以既是代码的存储空间,又是数据的存储空间还可以是栈空间也可以什么都不是。关键在于CPU中寄存器的设置,即CS,IP,SS,SP,DS的指向

实验2 用机器指令和汇编指令编程

猜你喜欢

转载自www.cnblogs.com/JasonPeng1/p/12116490.html
今日推荐