8086汇编--2--寄存器(内存访问)
By:wangyz
内存中字的存储
在16位CPU中,用十六位寄存器存储一个字,高八位存储高位字节,低八位存储低位字节。
在内存中存储时,由于内存单元是字节单元(一个单元存放一个字节),则一个字要用两个内存单元来存放,这个字的低位字节存放在低地址单元中,高位字节存放在高地址单元中
DS和[address]
CPU要读写一个内存单元时,必须先给出内存单元的地址,在8086中,内存地址由段地址和偏移地址组成。
8086CPU中又一个DS寄存器,通常用来存放要访问数据的段地址。
比如我们要读取10000H单元的内容
mov bx,1000H #bx=1000H
mov ds,bx #ds=1000H
mov al,[0]
上面三条指令将10000H(1000:0)中的数据读到al中
mov指令。可以直接将数据送入寄存器。也可以将一个寄存器的内容送入另一个寄存器
第三种用法是将一个内存单元的内容送入寄存器中。"mov 寄存器名,内存单元地址"
[......]表示一个内存单元,[0]中的0表示内存单元的偏移地址。但是只有偏移地址是不能定位一个内存单元的,8086中内存单元的段地址自动取ds中的数据为内存单元的段地址。
####
8086不支持将数据直接送入段寄存器的操作,ds是个段寄存器,所以mov ds,1000H这条指令是非法的。
可以使用一个其他寄存器进行中转,先将1000H送入一个一般寄存器bx,再将bx的内容送入ds
####
字的传送
把1000H放入ax ax=1000H
把ax的值放入ds ds=1000H
mov ax,[0] 把1000:0存放的字型数据放入ax,10000H单元存放字型数据的低八位为23H,10001H存放字型数据的高八位11H,所以10000H处存放的字型数据为1123H
指令执行时,字型数据的高八位送入ah,低八位送入al,
mov bx,[2] bx=6622H
mov cx,[1] cx=2211H
add bx,[1] bx=8833H
add cx,[2] cx=8833H
mov ax,1000H ax=1000H
mov ds,ax ds=1000H
mov ax,11316 11316=2C34H ax=2C34H
mov [0],ax ax中的字型数据送入1000:0处,ax的高八位2CH,低八位34H,指令执行中,低八位送入10000H处为34H,高八位送入10001H处为2CH
mov bx,[0] 10000H处的字型数据送入bx,10000H低八位为34H,10001H高八位为2CH,bx=2C34H
sub bx,[2] bx= bx-10002H=2C34H-1122H=1B12H
mov [2],bx bx=1B12H,低八位12H放入10002H中,高八位1BH放入10003H中,所以10002H=12H,10003H=1BH
mov,add,sub指令
数据段
栈
栈是一种具有特殊的访问方式的存储空间,先进后出
栈的两个基本操作
入栈和出栈,入栈就是将一个新的元素放到栈顶,出栈就是从栈顶取出元素。
栈顶的元素总是最后入栈,需要出栈时,又要最先从栈中取出
栈机制
8086提供相关指令来以栈的方式访问内存空间。这意味着在基于8086编程时,可以将一段内存当作栈来使用。
8086CPU提供入栈和出栈指令,最基本的两个是PUSH(入栈)和POP(出栈)
比如:push ax 表示将寄存器ax中的数据送入栈中,
pop ax 表示从栈顶取出数据送入ax。
8086的入栈和出栈操作都是以字为单位进行的
####
字型数据用两个单元存放,高危地址存放在高八位,低位地址存放在低八位
####
SS:SP
CPU如何知道栈顶的位置。8086中有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在SP中。
任意时刻,SS:SP指向栈顶元素。
push和pop指令执行时,cpu从ss和sp中得到栈顶地址。
完整的描述push和pop指令的功能,例如push ax执行时,由以下两步完成
1.sp=sp-2,SS;SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶。
2.将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶
栈顶超界的问题
SS和SP只是记录了栈顶地址,依靠SS和SP可以保证在入栈和出栈时找到栈顶。
如何能够保证入栈和出栈时,栈顶不会超出栈空间。
栈顶超界是危险的,既然我们将一段空间安排为栈,那么在栈空间之外的空间里很可能存放了具有其他用途的数据代码等,这些数据代码可能是我们自己程序中的,也可能是别的程序中的,但是由于我们在入栈出栈时不小心,而将这些数据代码改写,将会引发一连串错误。
在编写8086程序的时候要小心栈顶超界的问题,要根据需要来安排栈的大小,出栈时也要注意不要在栈空的时候继续出栈导致超界。
push和pop指令
push 寄存器; 将一个寄存器的数据入栈
pop 寄存器;用一个寄存器接受出栈的数据
push 段寄存器;将一个段寄存器中的数据入栈
pop 段寄存器;将出栈的数据送入段寄存器
push 内存单元;将一个内存单元处的字入栈;push [0];将1000:0处的字入栈
pop 内存单元;将出栈的数据送入内存单元;pop [2];出栈的数据送入1000:2处
问题1:编程,将10000H-1000FH这段空间当作栈,初始状态为空,将ax,bx,ds中的数据入栈
mov ax,1000H 将1000H放入ax,ax=1000H
mov ss,ax 将ax放入ss段寄存器,ss=1000H,用ax中转设置栈的段地址
mov sp,0010H 栈顶偏移地址为000FH,状态为空,那么sp应该为000FH+1H=0010H,所有sp=0010H,将0010H放入sp寄存器,设置栈顶偏移地址,
push ax
push bx
push ds
问题2:将10000H-1000FH这段空间当作栈,出师状态为空;设置AX=001AH,BX=001BH;将AX和BX数据入栈;然后将AX和BX清零;从栈中恢复AX和BX 的内容
mov ax,1000H 把1000H送入ax
mov ss,ax 设置SS为1000H
mov sp,0010H 初始化栈顶
mov ax,001AH
mov bx,001BH
push ax
pusn bx
sub ax,ax 清零操作,机器码2个字节
sub bx,bx 或者mov ax,0,机器码3个字节
pop bx
pop ax
问题3:如果要在10000H处写入字型数据2266H,用什么代码完成
mov ax,1000H
mov ds,ax
mov bx,2266H
mov [0],ax
问题4:如果将10000H-1FFFFH这段空间当作栈,初始状态为空,此时SS=1000H,SP=?
SS=1000H,栈空间为64KB,栈最底部的单元地址为1000:FFFEH。
任意时刻SS:SP指向栈顶单元,当栈中只有一个元素时,SS=1000H,SP=FFFEH。
栈为空,就相当于栈中唯一哟个元素出栈,SP=SP+2
SP原来等于FFFEH,加上2后SP=0,所以栈为空的时候,SS=1000H,SP=0