内存中字的存储
CPU中,用16位寄存器来存储一个字。
高8位存放高位字节,低8位存放低位字节。
内存单元是字节单元(一个单元存放一个字节),一个字要用两个地址连续的内存单元来存放。
用0、1两个内存单元存放数据20000(4E20H)
0是低地址单元 1是高地址单元
DS和[address]
CPU读写一个内存单元的时候,必须先给出这个内存单元的地址。
8086CPU中有一个DS寄存器,通常用来存放要访问数据的段地址。
读取10000H\
mov bx,1000H
mov ds,bx
mov al,[0]
将10000H(1000:0)中的数读到al中
[]表示一个内存单元,[]中的值表示内存单元的偏移地址
10000H 用段地址和偏移地址表示为 1000:0,我们先将段地址 1000H 放入 ds,然后用 mov al,[0]完成传送。mov 指令中的门说明操作对象是一个内存单元,[中的0说明这个内存单元的偏移地址是 0,它的段地址默认放在 ds 中,指令执行时,8086CPU 会自动从ds中取出。
将al中的数据送入内存单元10000H中
mov bx,1000h
mov ds,dx
mov [0],al
字的传送
只要在mov指令中给出16位的寄存器就可以进行16位数据的传送
mov bx,1000H
mov ds,bx
mov ax,[0] 1000:0处的字型数据送入ax
mov [0],cx cx中的16位数据送到1000:0处
问题:
内存中的情况为
、
执行项目的指令后寄存器ax,bx,cx中的值为什么
mov ax,1000H
mov ds,ax
mov ax,[0]
mov bx,[2]
mov cx,[1]
add bx,[1]
add cx,[2]
问题
mov、add、sub指令
mov指令的形式
mov 寄存器,数据 | mov ax,8 |
---|---|
mov 寄存器,寄存器 | mov ax,bx |
mov 寄存器,内存单元 | mov ax,[0] |
mov 内存单元,寄存器 | mov [0],ax |
mov 段寄存器,寄存器 | mov ds,ax |
add指令
add 寄存器,数据 | add ax,8 |
---|---|
add 寄存器,寄存器 | add ax,bx |
add 寄存器,内存单元 | add ax,[0] |
add 内存单元,寄存器 | add [0],ax |
sub指令
sub 寄存器,数据 | sub ax,8 |
---|---|
sub 寄存器,寄存器 | sub ax,bx |
sub 寄存器,内存单元 | sub ax,[0] |
sub 内存单元,寄存器 | sub [0],ax |
数据段
对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。我们可以将一组长度为 N≤64KB)、地址连续、起始地址为 16 的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。比如用 123BOH~123B9H 这段内存空间来存放数据,我们就可以认为,123B0H~123B9H 这段内存是一个数据段,它的段地址为 123BH,长度为 10个字节。
栈
栈是一种具有特殊的访问方式的存储空间。它的特殊性就在于,最后进入这个空间的数据,最先出去。
CPU提供的栈机制
8086CPU提供入栈和出栈指令 PUSH POP
push ax 表示将寄存器 ax 中的数据送入栈中,pop ax 表示从栈顶取出数据送入 ax。
8086CPU 的入栈和出栈操作都是以字为单位进行的。
mov ax,0123H
push ax
mov bx,2266H
push bx
mov cx,1122H
push cx
pop ax
pop bx
pop CX
8086CPU 中,有两个寄存器,段寄存器SS 和寄存器 SP,栈顶的段地址存放在 SS 中,偏移地址存放在 SP 中。任意时刻,SS:SP 指向栈顶元素。push 指令和pop 指令执行时,CPU 从 SS 和 SP 中得到栈顶的地址。
将 10000H~1000FH 这段空间当作栈段,SS=1000H,栈空间大小为16 字节,栈最底部的字单元地址为 1000:000E。任意时刻,SS:SP指向栈顶,当栈中只有一个元素的时候,SS=1000H,SP-000EH。栈为空,就相当于栈中唯一的元素出栈,出后,SP-SP+2,SP 原来为000EH,加2后 SP=10H,所以,当栈为空的时候,SS=1000H,SP=10H。
换一个角度看,任意时刻,SS:SP 指向栈顶元素,当为空的时候,中没有元素也就不存在栈顶元素,所以 SS:SP 只能指向栈的最底部单元下面的单元,该单元的偏移地址为栈最底部的字单元的偏移地址+2,栈最底部字单元的地址为 1000:000E,所以栈空时,SP-0010H.
pop ax 的执行过程和 push ax 刚好相反,由以下两步完成。
(1)将 SS:SP 指向的内存单元处的数据送入 ax 中;
(2)SP=SP+2,SS:SP 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
栈顶超界的问题
当栈满的时候再使用 push 指令入栈,或栈空的时候再使用 pop 指令出栈,都将发生栈顶超界问题。
8086CPU 不保证我们对栈的操作不会超界。这也就是说,8086CPU只知道栈顶在何处(由 SS:SP 指示),而不知道我们安排的栈空间有多大。这点就好像 CPU 只知道当前要执行的指令在何处(由 CS:IP 指示),而不知道要执行的指令有多少。从这两点上我们可以看出 8086CPU 的工作机理,它只考虑当前的情况:当前的栈顶在何处、当前要执行的指令是哪一条。
我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;执行出操作的时候也要注意,以防栈空的时候继续出栈而导致的超界。
push、pop指令
push 寄存器 | 将一个寄存器中的数据入栈 |
---|---|
pop 寄存器 | 出栈,用一个寄存器接收出栈的数据 |
push段寄存器 | 将一个段寄存器的数据入栈 |
pop段寄存器 | 出栈,用一个段寄存器接收出栈的数据 |
push内存单元 | 将一个内存字单元的字入栈 |
pop内存单元 | 出栈,用一个内存字单元接收出栈的数据 |