##DS和[address]
DS寄存器:通常用来存放要访问数据的段地址
[address]表示一个偏移地址为address的内存单元,段地址默认放在ds中
通过数据段段地址和偏移地址即可定位内存单元
mov bx, 1000H ;8086CPU不支持将数据直接送入段寄存器的操作
mov ds, bx ;ds存放数据段地址
mov al, [0];
这个要解释一下 mov 指令,完成两种传送, 1.数据直接送入寄存器,2 讲一个寄存器的内容送入另外一个寄存器。
所以也可以将一个内存单元的内容送入一个寄存器中,指令需要指名。寄存器用寄存器指名,内存单元则需要内存单元指名。
显然格式就是 mov 寄存器名, 内存单元
“[…]”表示一个内存单元,”[…]”中的0 表示内存单元的偏移地址。 自然这个也需要段地址,CPU 会自动取ds中的数据作为内存单元的段地址。 所以此时ds寄存器里面的内容已经是1000H。
注意: 不能使用mov ds,1000H的,因为ds是段寄存器,只能通过寄存器中转,这个属于硬件设计问题,跟软件无关
字的传送
因为8086是16位CPU ,可以一次性传送16位数据,书中是把16位数据当做一个字节
mov bx,1000H
mov ds,bx
mov ax,[0] ; 1000:0处的字型数据送入ax
mov [0],bx ; cx中的16位数据送到1000:0处
mov、 add 、 sub指令 格式一样
SS和SP 栈
在基于8086CPU编程的时候,可以将一段内存当作栈来使用。
如图指令执行的过程
mov ax,0123H
push ax
mov bx,2266H
push bx
mov cx,1122H
push cx
pop ax
pop bx
pop cx
注意,字型数据用两个单元存放
CPU 也有两个寄存器,段寄存器SS 和寄存器SP 栈顶的段地址存放在SS ,偏移地址存放在SP中,任意时刻,SS:SP 指向栈顶元素,所以push 和pop指令执行,cpu 会从ss和sp 得到栈顶地址。
栈段寄存器SS,存放段地址,SP寄存器存放偏移地址,任意时刻,SS:SP指向栈顶元素
8086CPU中,入栈时,栈顶从高地址向低地址方向增长。
push ax表示将寄存器ax中的数据送入栈中,由两步完成。
SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶; 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。
pop ax表示从栈顶取出数据送入ax,由以下两步完成。
将SS:SP指向的内存单元处的数据送入ax中; SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
栈顶超界问题
执行push导致超出栈顶空间
执行pop导致超出栈空间
该例子提醒我们编程的时候一定要注意避免超出栈空间错误,CPU 并没有这样的寄存器检查栈顶地址是否超出空间。
实验
1.将10000H~1000FH这段空间当作栈,初始状态栈是空的; 2.设置AX=001AH,BX=001BH; 3.将AX、BX中的数据入栈; 4.然后将AX、BX清零; 5.从栈中恢复AX、BX原来的内容。 代码如下:
mov ax, 1000H
mov ss, ax
mov sp, 0010H ;初始化栈顶
mov ax, 001AH
mov bx, 001BH
push ax
push bx ;ax、bx入栈
sub ax, ax ;将ax清零,也可以用mov ax,0,
;sub ax,ax的机器码为2个字节,
;mov ax,0的机器码为3个字节。
sub bx, bx
pop bx ;从栈中恢复ax、bx原来的数据
pop ax ;