再次声明,默认采用小端法在内存中存储数据。
在8086PC中,定位一个内存地址需要由段地址和偏移地址一起来完成。注意:当编写指令想要读取某个内存单元中的数据时,需要对偏移地址加上中括号’[ ]'。表示读取该地址上的数据。
在编程时可以根据需要将一组内存单元定义为一个段。这段内存单元需要满足:代码长度不能大于64KB,必须是连续的内存单元,内存的起始地址为16的整数倍。当我们将数据存放在这样的内存单元中时,就可以将其定义为一个数据段。一般的,用DS来存放数据段的段地址,用BX来表示偏移地址。
如:将123B0H-123B9H内存单元定义为一个数据段。并且累加数据段中前三个字节单位中的数据。
mov ax,123BH
mov ds,ax 8086CPU不能直接将立即数传送到段寄存器中
mov al,0
add al,[0]
add al,[1]
add al,[2]
在编程时可以根据需要将一组内存单元定义为一个段。这段内存单元需要满足:代码长度不能大于64KB,必须是连续的内存单元,内存的起始地址为16的整数倍。当我们要将这段内存单元作为栈空间来使用时,就可以认为它是一个栈段。用SS来存放栈段的段地址,用SP来指向栈顶。在任意时刻,SS:SP指向栈顶元素。
入栈指令push,表示将某个数据压入栈中,操作对象大小必须为一个字。push ax的具体执行过程为:(1)SP=SP-2。(2)将ax中的内容送到SS:SP指向的内存单元处。入栈时,栈顶由高地址向低地址方向增长。
出栈指令pop,表示从栈中弹出栈顶数据,操作对象大小必须为一个字。pop ax的具体执行过程为:(1)将SS:SP指向的内存单元处的数据送入ax。(2)SP=SP+2。出栈时,栈顶由低地址向高地址方向增长。
例:若将10000H-1000FH这段空间看作为一个栈,初始状态栈为空。此时如果SS=1000H,那么SP=0010H。
注意:关于栈顶向上或向下超界的问题需要用户编程时自己注意。并且一个很有意思的点是:一个栈段的最大容量,亦或一个段的最大容量是64KB,这是由16位的偏移地址决定。如果一个栈段刚好是64KB时,即栈顶(偏移地址)变化范围为:0-FFFFH。首先当栈空时,SP为0000。随着不断有数据入栈,SP会不断减小,如FFFEH,FFFCH…0002H,0000H。我们可以发现当整个栈是满的的时候,SP也为0000。此时如果再有数据入栈,SP依然会不断减小,如FFFEH,FFFCH…0002H,0000H,也就是说新的数据会覆盖掉栈空间中以前的所有元素。
mov指令使用形式如下:
指令 | op1 | op2 | 示例 |
---|---|---|---|
mov | 寄存器 | 数据 | mov ax,8 |
mov | 寄存器 | 寄存器 | mov ax,bx |
mov | 寄存器 | 内存单元 | mov ax,[8] |
mov | 内存单元 | 寄存器 | mov [8],ax |
mov | 段寄存器 | 寄存器 | mov ds,ax |
mov | 寄存器 | 段寄存器 | mov ax,ds |
mov | 段寄存器 | 内存单元 | mov ds,[8] |
mov | 内存单元 | 段寄存器 | mov [8],ds |
add、sub指令使用形式如下: | |||
指令 | op1 | op2 | 示例 |
– | – | – | – |
add | 寄存器 | 数据 | add ax,8 |
add | 寄存器 | 寄存器 | add ax,bx |
add | 寄存器 | 内存单元 | add ax,[8] |
add | 内存单元 | 寄存器 | add [8],ax |
sub | 寄存器 | 数据 | sub ax,8 |
sub | 寄存器 | 寄存器 | sub ax,bx |
sub | 寄存器 | 内存单元 | sub ax,[8] |
sub | 内存单元 | 寄存器 | sub [8],ax |
注意:不能将数据直接传送到段寄存器中;不能将段寄存器作为add/sub的操作对象。 |
除法规则:
(1)除数:有8位或16位两种,可以放在reg或内存单元中。
(2)被除数:默认放在AX或DX,和AX中,如果除数为8位,被除数则为16位,默认放在AX中;如果除数为16位,被除数则为32位,在DX和AX中存放,DX中存放高16位,AX中存放低16位。
(3)结果:如果除数为8位,则AL存储除法操作的商,AH存储除法操作的余数;如果除数为16位,则AX存储除法操作的商,DX存储除法操作的余数;
如:div bl div bx div byte ptr ds:[0] div word ptr ds:[0]
乘法规则:
(1)两个相乘的数,要么都是8位,要么都是16位。如果是8位,一个默认放在AL中,另一个放在8位寄存器或内存字节单元中;如果是16位,一个默认放在AX中,另一个放在16位寄存器或内存字单元中
(2)结果:如果是8位乘法,结果默认放在AX中;如果是16位乘法,结果的高位默认放在DX中,低位放在AX中;
如:mul bl mul bx mul byte ptr ds:[0] mul word ptr ds:[0]
这两种指令均要用到标志寄存器中的cf标志位上的进位值或借位值。这两种指令的作用都是用来进行对大整数进行加减法操作的。
指令格式:adc op1,op2效果为:op1=op1+op2+cf
示例:对于0198H和0183H相加的运算
(1)直接16位相加。
指令为:mov ax,0198H mov bx,0183H add ax,bx
(2)也可以先将低8位相加,再将高8位相加,注意低8位相加会产生进位。
指令为:mov ax,0198H mov bx,0183H add al,bl adc ah,bh
例:编写程序将两个128位数据相加,ds:si存放第一个数,ds:di存放第二个数,将结果保存在第一个数的内存空间中。
采用带进位的加法指令从最低位开始相加,128位是8个字,需循环8次。代码如下:
sub ax,ax 设置cf位为0
mov cx,8 设置循环次数为8
s:mov ax,[si]
adc ax,[di]
mov [si],ax
inc si inc指令不影响cf位
inc si
inc di
inc di
loop s loop指令不影响cf位
指令格式:sbb op1,op2效果为:op1=op1-op2-cf
示例:计算003E1000H-00202000H的,将结果放在ax,bx中,程序如下:
mov bx,1000EH bx中存放高16位
mov ax,003EH ax中存放低16位
sub bx,2000H
sbb ax,0020H
adc、sbb都是先对低位做运算,后对高位做运算。