第 3 章 寄存器(内存访问)

1.内存中字的存储
字的低位字节存放在低地址单元中,高位字节存放在高地址单元中。
0、1两个内存单元用来存储一个字,这两个单元可以看做一个起始地址为0的字单元。
我们提出字单元的概念:字单元,即存放一个字型数据(16位)的内存单元,由两个地址连续的内存单元组成。
在以后的课程中,我们将起始地址为N的字单元简称为N地址字单元。
2.DS和[address]
8086CPU中有一个DS寄存器,通常用来存放要访问数据的段地址。
"[...]"表示一个内存单元,"[...]"中的0表示内存单元的偏移地址。我们知道,只有偏移地址是不能定位一个内存单元的,那么内存单元的段地址是多少呢?指令执行时,8086CPU自动取ds中的数据为内存单元的段地址。
可是,现实并非如此,8086CPU不支持将数据直接送入段寄存器的操作,ds是一个段寄存器,所以mov ds,1000H这条指令是非法的。那么如何将1000H送入ds呢?只好用一个寄存器来进行中转,即先将1000H送入一个一般的寄存器,如bx,再将bx中的内容送入ds。
3.字的传送
因为8086CPU是16位结构,有16跟数据线,所以,可以一次性传送16位的数据。只要在mov指令中给出16位的寄存器就可以进行16位数据的传送了。
如:
mov ax,[0]
mov [0],cx
因为,ax跟cx都是16位的寄存器,所以,传输的是16位的数据,占据内存的两个内存单元。
4.数据段
我们可以将一组长度为N(N<=64KB)、地址连续、起始地址为16的倍数的内存单元当做专门存储数据的内存空间,从而定义了一个数据段。
如何访问数据段中的数据呢?
具体操作时,可以用ds存放数据段的段地址,再根据需要,用相关指令访问数据段中的具体单元。
比如:
add al,[0];将数据段第一个单元(偏移地址为0)中的数值加到al中
add ax,[0];将数据段第一个字(偏移地址为0)加到ax中
注意上面两者的区别:一个操作的是8位寄存器,一个是16位寄存器
5.栈
在这里,我们对栈的研究仅限于这个角度:栈是一种具有特殊的访问方式的存储空间。它的特殊性在于,最后进入这个空间的数据,最先出去。
从程序化的角度来讲,应该有一个标记,这个标记一直指示着盒子最上边的书。
栈的这种操作规则被称为:LIFO(Last In First Out,后进先出)。
6.CPU提供的栈机制
现今的CPU中都有栈的设计,8086CPU也不例外。8086CPU提供相关的指令来以栈的方式访问内存空间。这意味着,在基于8086CPU编程的时候,可以将一段内存当做栈来使用。
8086CPU提供入栈和出栈指令,最基本的两个是PUSH(入栈)和POP(出栈)。8086CPU的入栈和出栈操作都是以字为单位进行的。


图片1.png

上图是将10000H---1000FH这段内存当做栈来使用(执行入栈操作时,最先存储到1000FH和1000EH这两个单元)。
问题1:
CPU如何知道10000H----1000FH这段空间被当做栈来使用?
问题2:
push ax等入栈指令执行时,要将寄存器中的内容放入当前栈顶单元的上方,称为新的栈顶元素;pop ax等指令执行时,要从栈顶单元中取出数据,送入寄存器中。显然,push、pop在执行的时候,必须知道哪个单元是栈顶单元,可是,怎么知道呢?
答案:
8086CPU中,有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在SP中。任意时刻,SS:SP指向栈顶元素。
现在,我们可以完整地描述push和pop指令的功能了,例如push ax。
push ax的执行,由以下两部完成。
(1)SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;
(2)将ax中的内容送入SS:SP指向的内存单元中,SS:SP此时指向新栈顶。


图片2.png

从上图可以看出,8086CPU中,入栈时,栈顶从高地址向低地址方向增长。
栈空的状态?
如果将10000H--1000FH这段空间当做栈,初始状态栈是空的,此时,SS=1000H,SP=?
答案:
SP=0010H,如图3.11所示。
图片3.png

图片4.png

注意,图3.12中,出栈后,SS:SP指向新的栈顶1000EH,pop操作前的栈顶元素,1000CH处的2266H仍然存在,但是,它以不在栈中。当再次执行push等入栈指令后,SS:SP移至1000CH,并在里面写入新的数据,它将被覆盖。
7.栈顶超界的问题
8.push、pop指令
mov ax,1000H
mov ss,ax
mov sp,0010H
上面的3条指令设置栈顶地址(对于8086CPU而言,只能通过这种编程的方式来设置栈空间的大小)。编程中要自己注意栈的大小。
9.栈段
我们可以将长度为N(N<=64KB)的一组地址连续、起始地址为16的倍数的内存单元,当做栈空间来用,从而定义了一个栈段。
将一段内存当做栈段,仅仅是我们在编程的一种安排,CPU并不会由于这种安排,就在执行push、pop等栈操作指令时自动地将我们定义的栈段当做栈空间来访问。如何使得如push、pop灯展操作指令访问我们定义的栈段呢?就要将SS:SP指向我们定义的栈段。
问题:
如果将10000H---1FFFFH这段空间当做栈段,初始状态栈是空的,此时,SS=1000H,SP=?
答案:
注意SP的范围是0000H---FFFFH,所以,当栈为空的时候,SS=1000H,SP=0。
问题:
一个栈段最大可以设为多少?为什么?
答案:
我们可以将一段内存定义为一个段。我们可以用一个段当做栈,将它定义为“栈段”。所以,可以有多大的段,就会有多大的栈段。
一段内存,既可以是代码的存储空间,有时数据的存储空间,还可以是栈空间,也可以什么也不是。关键在于CPU中寄存器的设置,即CS、IP,SS、SP,DS的指向。

你可能感兴趣的:(第 3 章 寄存器(内存访问))