算术运算指令是反映CPU运算能力的一组指令,也是编程时经常使用的一组指令。因为算术运算类指令是在ALU中完成的,所以算术运算类指令对标志寄存器的内容均有影响,必须特别注意。算术运算指令共有以下5种类型。
· 二进制无符号数的算术运算指令。
· 二进制带符号数的算术运算指令。
· 无符号组合式BCD码加减运算指令。
· 无符号分离式BCD码算术运算指令。
· 多字节数运算指令。
(1)ADD——加法指令。
形式:ADD 目标操作数,源操作数。
功能:目标操作数←(目标操作数)+(源操作数)。
该指令有如下5种形式:
ADD R,R ; 通用寄存器之间相加
ADD R,Im ; 通用寄存器与立即数之间相加
ADD M,Im ; 内存数与立即数相加
ADD M,R ; 内存数与通用寄存器之间相加
ADD R,M ; 通用寄存器与内存数之间相加
例如,设(AX)=4,(BX)=200H,(DX)=6,(DI)=500H,(DS:502)=2
ADD AX,BX ; 语句执行后(AX)=204H
ADD DX,2[DI] ; 语句执行后(DX)=8
(2)SUB——减法指令。
形式:SUB 目标操作数,源操作数。
功能:目标操作数←(目标操作数)-(源操作数)。
该指令有如下5种形式:
SUB R,R ; 通用寄存器之间相减
SUB R,Im ; 通用寄存器与立即数之间相减
SUB M,Im ; 内存数与立即数相减
SUB M,R ; 内存数与通用寄存器之间相减
SUB R,M ; 通用寄存器与内存数之间相减
例如,设(CX)=10,(DX)=2,(BX)=5,OFFSET SW=100,(DS:105)=3
SUB CX,DX ; 语句执行后(CX)=8
SUB CH,DI ; 语句执行后(CH)=-2
SUB DX,SW[BX] ; 语句执行后(DX)=-1
(3)MUL——乘法指令。
形式:MUL 操作数。
功能:当操作数为字节数据时,AX←(操作数)×(AL);当操作数为字数据时,DX·AX←(操作数)×(AX)。
该指令有如下两种形式:
MUL R ; 8位寄存器时AX←(R)×(AL); 16位寄存器时DX·AX←(R)×(AX)
MUL M ; 字节类型时AX←(M)×(AL); 字类型时DX·AX←(M)×(AX)
对于单操作数的指令,要特别注意操作数的类型要明确。
MUL [SI]
MUL 2[DI]
MUL [BX ][SI ]
若从操作数的表示形式可以看出操作数都是M,也就是说都是内存数,但从操作数的表示形式中,我们能确定是进行字节乘法还是字乘法。所以以上指令都是错误的。
(4)DIV——除法指令。
形式:DIV 操作数。
功能:当操作数为字节数据时,AL←(AX)/(操作数),AH←(AX)MOD(操作数);当操作数为字数据时,AX←(DX·AX)/(操作数),DX←(DX·AX)MOD(操作数)。
该指令有如下两种形式:
DIV R ; 8位寄存器时AL←(AX)/(R), AH←(AX)MOD(R)
; 16位寄存器时AX←(DX·AX)/(R), DX←(DX·AX)MOD(R)
DIV M ; 字节类型时AL←(AX)/(M), AH←(Ax)MOD(M)
; 字类型时AX←(DX·AX)/ (M), DX←(DX·AX)MOD(M)
除法有溢出问题,凡字节运算商超过255或字运算商超过65535时均为溢出,0做除数也为溢出。除法出现溢出时,将立即产生0号中断,程序停止执行。
(5)CMP——比较指令。
形式:CMP 目标操作数,源操作数。
功能:(目标操作数)-(源操作数)。
该指令有如下5种形式:
CMP R,R ; 通用寄存器之间比较
CMP R,Im ; 通用寄存器与立即数之间比较
CMP M,Im ; 内存数与立即数相减
CMP M,R ; 内存数与通用寄存器之间比较
CMP R,M ; 通用寄存器与内存数之间比较
可以看出,比较指令与减法指令不同之处是所产生的两数之差并不取代目标操作数,指令执行后的结果仅仅体现在改变了标志寄存器的内容,为后面的具有判别功能的指令提供条件。
(6)INC——加1指令。
形式:INC 操作数。
功能:操作数←(操作数)+1。
该指令有如下两种形式:
INC R ; R←(R)+1
INC M ; M←(M)+1
(7)DEC——减1指令。
形式:DEC 操作数。
功能:操作数←(操作数)-1。
该指令有如下两种形式:
DECR ; R←(R)-1
DECM ; M←(M)-1
(8)NEG——求负指令。
形式:NEG 操作数。
功能:操作数←0 -(操作数)。
该指令有如下两种形式:
NEGR ; R←0-(R)
NEGM ; M←0-(M)
例如,8位[-3]补码=11111101B=0FDH,执行如下指令:
MOVAL,-3 ; AL←0FDH
NEGAL ; AL←0-0FDH=03H,03H就是-3的负数
MOVAL,3 ; AL←03H
NEGAL ; AL←0-03H=0FDH,0FDH就是3的负数
(1)ADD/SUB——加法/减法指令。
对于二进制符号数的加减法运算,由于系统采用补码表示法,故与无符号数的加减法指令是一样的。一个二进制数既可以看成符号数,也可以看成无符号数,但由于这两种数的数值范围不同,故判断溢出的方法不同。对无符号数的加减法不存在溢出问题,只将进位或借位情况记录在CF中。对符号数的溢出要查看标志位的OF记录,(OF)=1为溢出,(OF)=0没有溢出。这是因为,对于符号数,若运算结果溢出了,那么运算结果也就是错误的,也就没有必要继续程序的执行,这时往往要转向溢出处理程序的执行。所以,对ADD或SUB进行的运算,查不查看标志位CF或OF,运算结果是否可取,这都取决于机器进行的是无符号运算还是符号数运算。这个问题只有编程者自己清楚,机器是不知道的。
(2)IMUL——符号数乘法指令。
形式:IMUL 操作数。
功能:当操作数为字节数据时,AX←(操作数)×(AL);当操作数为字数据时,DX·AX←(操作数)×(AX)。
该指令有如下两种形式:
IMUL R ; 8位寄存器时AX←(R)×(AL); 16位寄存器时DX·AX←(R)×(AX)
IMUL M ; 字节类型时AX←(M)×(AL); 字类型时DX·AX←(M)×(AX)
例如:
wNum DW 8004H ; (wNum)=8004H
MOV AX,5 ; AX←5
MUL wNum ; DX←0002H, AX←8014H
IMUL wNum ; DX←0FFFDH, AX←8064H
(3)IDIV——符号数除法指令。
形式:IDIV 操作数。
功能:当操作数为字节数据时,AL←(AX)/(操作数),AH←(AX)MOD OPRD;当操作数为字数据时,AX←(DX·AX)/(操作数),DX←(DX.AX)MOD OPRD。
该指令有如下两种形式:
IDIV R ; 8位寄存器时AL←(AX)/(R), AH←(AX)MOD(R)
; 16位寄存器时AX←(DX×AX)/(R), DX←(DX×AX)MOD OPRD
IDIV M ; 字节类型时AL←(AX)/(M), AH←(AX)MOD(M)
; 字类型时AX←(DX×AX)/(M), DX←(DX×AX)MOD(M)
如果商溢出(字节运算时商超过-128~127,或字运算时商超过-32768~32767),则产生0号中断。如果被除数不是除数的两倍长度,则要把被除数低一半的符号位填充到高一半中,变成除数的双倍长度。其相应的支持指令为:
形式:CBW。
功能:将AL中的符号扩展到AH中,即将一个字节的带符号数扩展成一个字。
形式:CWD。
功能:将AX中的符号扩展到DX中,即将一个字的带符号数扩展成双字。
例如:
SW DB-9
DATA DB 2
MOV AL,SW
CBW
IDIV DATA ;(AL)=4
对于无符号组合式BCD码的运算,系统是利用二进制数运算然后再进行修正的方法来实现的。由于组合式十进制数采用4位二进制数表示一个数,故4位二进制数中只有0~9是有效的,而10~15是无效的,并且4位二进制数中若有进位时,表示的是16进一,而不是10进一。这样,用二进制运算组合式BCD时就产生两个问题:一是运算的结果大于9时而不知道进位到高4位中;二是低4位进位到高4位的“1”不代表10而是16。为此,系统设立了一个辅助进位标志位AF(执行加法指令时,若低4位产生进位则AF置位,反之AF被清零。执行减法指令时若低4位产生借位则AF置位,反之AF被清零)及两个调整语句。
(1)DAA——加法调整指令。
形式:DAA。
功能:如果AL寄存器中低4位大于9或辅助进位(AF)=1,则(AL)= (AL)+6并且(AF=1);如果(AL)≥0A0H或(CF)=1,则(AL)= (AL)+60H并且(CF)=1。
(2)DAS——减法调整指令。
形式:DAS。
功能:如果AL寄存器中低4位大于9或辅助借位(AF)=1,则(AL)=(AL)-6并且(AF)=1;如果(AL)≥0A0H或(CF)=1,则(AL)=(AL)-60H并且(CF)=1。
进行组合式BCD码加法或减法运算实现用ADD语句或SUB语句,使运算结果在AL中,然后再应用DAA或DAS调整语句即可得组合式BCD加减法的正确结果。
例如:
MOVAL,43H ;(AL)=43H
MOVBL,29H ;(BL)=29H
ADDAL,BL ;(AL)=6CH
DAA ;(AL)=72H
MOVAL,43H ;(AL)=43H
MOVBL,29H ;(BL)=29H
SUBAL,BL ;(AL)=IAH
DAS ;(AL)=14H
无符号分离式BCD运算也是在二进制无符号四则运算的基础上再增加4种调整功能实现的。无符号分离式BCD可进行四则运算,因而相应有4种调整指令,它都是对字节运算进行调整的。
(1)AAA——ASCII加法调整指令。
形式:AAA。
功能:如果AL的低4位大于9或(AF)=1,则(AL)=(AL)+6,(AH)=(AH)+1,(AF)=(CF)=1,AL高4位清零;否则(AF)=(CF)=0,AL高4位清零。
例如:
MOVAH,0
MOVAL, '7' ;(AL)=37H
MOVBL, '4' ;(BL)=34H
ADDAL, BL ;(AL)=6BH
AAA ;(AX)=0101H
(2)AAS——ASCII减法调整指令。
形式:AAS。
功能:如果AL的低4位大于9或(AF)=1,则(AL)=(AL)-6,(AH)=(AH)-1,(AF)=(CF))=1,AL高4位清零;否则(AF)=(CF)=0,AL高4位清零。
(3)AAM——ASCII乘法调整指令。
形式:AAM。
功能:被调整的乘积在AX中,其调整规则为AH←(AL)/10,AL←(AL)%10。
例如:
MOV AL,'9' ;(AL)=39H
MOV BL,'8' ;(BL)=38H
SUB AL,30H ;(AL)=09H,高4位清0
SUB BL,30H ;(BL)=08H,高4位清0
MUL BL ;(AX)=0048H
AAM ;(AX)=0702H
(4)AAD——ASCII除法调整指令。
形式:AAD。
功能:除法运算前,先调整AX内容,使(AL)=(AL)+(AH)×10,(AH)=0,即把非压缩十进制数变成二进制数。
从以上可以看出,由于ASCII码中0~9字符的低4位用相应的0~9表示,而高4位都是用3表示,且分离式BCD的加减运算中,参加运算的数的高4位可取任意值,但在乘除运算时,参加运算数的高4位须为0。
【例9-3】 编写程序实现输入任意两个0~9之间的数字,并分别进行加法与乘法运算,运算后显示在屏幕上。
注意:由于输入与输出的数据均为ASCII码,故用分离式BCD码较为方便;又由于程序很简单,故采用寄存器CX存放数据,不设置数据段。
源程序:
.MODEL SMALL
. .STACK 100H
.CODE
LAA:MOV AH,1 ; 从键盘输入两个数
INT 21H
MOV CH,AL
MOV AH,1
INT 21H
MOV AH,0 ; 求和
MOV CL,AL ; 两个数在CX中保存
ADD AL,CH
AAA
ADD AX,3030H ; 显示和
MOV DH,AL
MOV DI,AH
MOV AH,2
INT 21H
MOV DI,DH
MOV AH,2
INT 21H
SUB CX,3030H ; 求积
MOV AL,CL
MUL CH
AAM
ADD AX,3030H ; 显示积
MOV DH,AL
MOV DI,AH
MOV AH,2
INT 21H
MOV DI,DH
MOV AH,2
INT 21H
.EXIT 0
END LAA
运行结果:
891772
运用前面讲的定字长的二进制与十进制数的运算指令,配合这里讲的两条指令,就可以实现多字节的运算。
(1)ADC——带进位加法指令。
形式:ADC 目标操作数,源操作数。
功能:目标操作数←(目标操作数)+(源操作数)+CF。
该指令有如下5种形式:
ADC R,R ; 通用寄存器之间相加,再加进位位
ADC R,Im ; 通用寄存器与立即数之间相加,再加进位位
ADC M,Im ; 内存数与立即数相加,再加进位位
ADC M,R ; 内存数与通用寄存器之间相加,再加进位位
ADC R,M ; 通用寄存器与内存数之间相加,再加进位位
例如,380782H+65C2H的程序片段如下:
bNum1 DB 0B2H,07H,38H
bNum2 DB 0C2H,65H
MOV AL,bNum1
ADD AL,bNum2
MOV AH,bNum1+1
ADC AH,bNum2+1
MOV DI,bNum1+2
ADC DI,0
(2)SBB——带借位减法指令。
形式:SBB 目标操作数,源操作数。
功能:目标操作数←(目标操作数)-(源操作数)-CF。
该指令有如下5种形式:
SBB R,R ; 通用寄存器之间相减,再减借位位
SBB R,Im ; 通用寄存器与立即数之间相减,再减借位位
SBB M,Im ; 内存数与立即数相减,再减借位位
SBB M,R ; 内存数与通用寄存器之间相减,再减借位位
SBB R,M ; 通用寄存器与内存数之间相减,再减借位位
实现多字节减法和实现多字节加法方法一样。实现多字节乘法及除法的思想可通过下面的程序来体现。
例如,380782H×C2H的程序片段如下:
bMul1 DB 82H,07H,38H
bMul2 DB 0C2H
bResult DB 4 DUP(0)
MOV AL,bMul1
MUL bMul2
MOV bResult,AL
MOV bResult+1,AH
MOV AL,bMul1+1
MUL bMul2
ADD bResult+1,AL
ADC bResult+2,AH
MOV AL,bMul1+2
MUL bMul2
ADD bResult+2,AL
ADC bResult+3,AH
又如,380782H+C2H的程序片段如下:
bDiv1 DB 0B2H,07H,38H
bDiv2 DB 0C2H
bResult DB 4 DUP(0)
MOV AH,0
MOV AL,bDiv1+2
DIV bDiv2
MOV bResult,AL
MOV AL,bDiv1+1
DIV bDiv2
MOV bResult+1,,AL
MOV AL,bDiv1
DIV bDiv2
MOV bResult+2,AL
MOV bResult+3,AH