一、内存中字的存储
字单元的概念:字单元,即存放一个字型数据(16 位)的内存单元,由两个地址连续的内存单元组成
由上一章学习可知:高地址内存单元中存放字型数据的高位字节,低地址内存单元中存放字型数据的低位字节
现在有以下几个问题
(1) 0 地址单元中存放的字节型数据是多少? 20H
(2) 0 地址字单元中存放的字型数据是多少? 4E20H
(3) 2 地址单元中存放的字节型数据是多少? 12H
(4) 2 地址字单元中存放的字型数据是多少? 0012H
(5) 1 地址字单元中存放的字型数据是多少? 4E12 H
注意: 1 地址字单元,即起始地址为 1 的字单元,它由 1 号单元和 2 号单元组成
二、DS 和 [address]
8086 CPU 中有一个 DS 寄存器,通常用来存放要访问数据的段地址。比如我们要读取 10000H 单元的内容,可以用如下的程序段进行:
mov bx,1000H
mov ds,bx
mov al,[0]
上面的 3 条指令将 10000H(1000:0) 中的数据读到 al 中
8086 CPU 自动取 ds 中的数据为内存单元的段地址 ,"[...]"表示一个内存单元,"[...]"中的 0 表示内存单元的偏移地址
另一个案例,如果将 10000H 单元的内容送入 al 中呢
mov [0],al
三、字的传送
前面我们用 mov 指令在寄存器和内存之间进行字节型数据的传送(8 位)
只要在 mov 指令中给出 16 位的寄存器就可以进行 16 位数据的传送了
四、数据段
比如,将 123B0H~123B9H 的内存单元定义为数据段。现在要累加这个数据段中的前3 个单元中的数据,代码如下:
mov ax,123BH
mov ds,ax
mov al,0
add al,[0]
add al,[1]
add al,[2]
..............................
答案解析:
五、栈
六、CPU 提供的栈机制
8086 CPU 提供入栈和出栈指令,最基本的两个是 PUSH(入栈) 和 POP(出栈)。
8086 CPU 的入栈和出栈操作都是以字为单位进行的
请看以下指令
mov ax,0123H
push ax
mov bx,2266H
push bx
mov cx,1122H
push cx
pop ax
pop bx
pop cX
指令执行过程如下
8086 CPU 中,有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在 SS 中,偏移地址存放在 SP 中
任意时刻,SS:SP 指向栈顶元素
pop 指令执行过程
七、栈顶超界问题
8086 CPU 不保证我们对栈的操作不会超界
总结:我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;执行出操作的时候也要注意,以防栈空的时候继续出栈而导致的超界。
八、push、pop 指令
push 寄存器
push 段寄存器
push 内存单元
pop 寄存器
pop 段寄存器
pop 内存单元
编程:
将 10000H~1000FH 这段空间当作栈,初始状态栈是空的,将 AX、BX、DS
中的数据入栈
mov ax,1000H ;设置栈的段地址,SS=1000H,不能直接向段寄存器SS中送入数据,所以用 ax 中转
mov ss,ax
mov sp,0010H
push ax
push bx
push cx
编程:
将 10000H~1000FH 这段空间当作栈,初始状态栈是空的,设置 AX-001AH,BX-001BH:将 AX、BX 中的数据入栈,然后将 AX、BX 清零,从栈中恢复 AX、BX 原来的内容
mov ax,1000H
mov ss,ax
mov sp,0010H ;初始化栈顶
mov ax,001AH
mov bx,001BH
push ax
push bx
mov ax,0
mov bx,0
pop bx
pop ax
mov ax,1000H
mov ss,ax
mov sp,0002H
mov ax,2266H
push ax
push ax 是入栈指令,它将在栈顶之上压入新的数据。一定要注意:它的执行过程是,先将记录栈顶偏移地址的 SP 寄存器中的内容减 2,使得 SS:SP 指向新的栈顶单元,然后再将寄存器中的数据送入 SS:SP 指向的新的栈顶单元
原因:因为 8086 处理器是从高地址到低地址增长栈
九、栈段
如果将 10000H~IFFFFH 这段空间当作栈段,初始状态是空的,此时,SS=1000H,SP=?
栈段基址和栈指针的初始值
- 栈段寄存器(SS)确定栈段的基址。给定SS = 1000H,那么栈段基址为10000H。
- 栈指针(SP)指示当前栈顶的偏移量。对于一个空栈,SP的初始值应指向栈段的末尾,以便第一次
PUSH
操作能够在栈的顶部进行。
栈指针初始值的计算
8086处理器的栈段从高地址向低地址增长。即:
- 栈顶在栈段的高地址。
- 栈底在栈段的低地址。
为了确保栈初始为空,我们需要将SP设置为指向栈段的最高地址的下一个字(word)。
栈段范围是从10000H到1FFFFH,总大小为FFFFH字节。栈段最高地址是1FFFFH,如果初始SP指向1FFFFH,那么第一个 PUSH
操作会将数据放在1FFFDH和1FFFEH(SP减2后)的位置。因此,我们设置SP为栈段的最大容量加1,即栈段结束地址的下一个位置。
具体步骤
-
计算栈段大小:
- 栈段基址 = 10000H
- 栈段结束 = 1FFFFH
- 栈段大小 = 1FFFFH - 10000H + 1 = FFFFH + 1 = 10000H
-
设置初始SP:
- 初始SP = 栈段大小 = 10000H
由于8086处理器中的栈操作将SP减2后再存储数据,这样设置SP可以保证在第一次PUSH操作时SP减2后刚好在1FFFEH和1FFFDH位置存储数据。