3.3.1 算术运算指令 8088可提供加、减、乘、除4种基本算术运算的操作指令。这些指令可实现字节或字的运算,也可以用于符号数和无符号数的运算。
8088还提供各种校正操作,故可以进行十进制的算术运算。进行加、减运算的源操作数和目的操作数的关系如图3.15所示。
1.加法指令
(1)ADDOPRD1,OPRD2
这条指令完成两个操作数相加,结果送至目的操作数OPRD1,即OPRD1←OPRD1+OPRD2目的操作数可以是累加器、任一通用寄存器或存贮器中的操作数。
具体地说,该指令可以实现累加器与立即数、累加器与任一通用寄存器、累加器与存贮单元内容相加,其和放回累加器中,
例如:
ADD AL,30
ADD AX,3000H
ADD AX,SI
ADD AL,DATA
该指令也可以实现任一通用寄存器与立即数、累加器或别的寄存器、存贮单元的内容相加,其和放回寄存器中,
例如:
ADD BX,3FFH
ADD SI,AX
ADD DI,CX
ADD DX,DATA[BX+SI]
该指令还可以实现存贮器操作数与立即数、累加器或别的寄存器的内容相加,其和放回存贮单元中,
例如
ADD BETA[SI],100
ADD BETA[SI],AX
ADD BETA[SI],DX
这些指令执行时,对标志位CF、OF、PF、SF、ZF和AF都会产生影响。
(2) ADC指令
这条指令与ADD指令基本相同,只是在对两个操作数进行相加运算时还应加上进位位的当前值,然后再将结果送至目的操作数。
例如,两个四字节数已分别放在首地址为FIRST和SECOND的内存区中。每个数占4个存贮单元,存放时低字节在前,高字节在后。那么用如下ADD
和ADC指令就可实现四字节数的相加,相加结果放入THIRD为首地址的单元中。
MOV AX, FIRST
ADD AX, SECOND
MOV THIRD,AX
MOV AX, FIRST+2
ADC AX,SECOND+2
MOV THIRD+2,AX
该指令对标志位的影响与ADD指令对标志位的影响相同。
(3) INCOPRD指令
这条指令对指定的操作数进行加1操作,在循环程序中常用于修改地址指针和循环次数等。其操作数可以在通用寄存器中,也可以在内存单元中。
该指令执行结果对标志位AF、OF、PF、SF和ZF有影响,而对CF位不产生影响.
例如:
INC AL
INC[SI] ;
2. 减法指令
(1)SUBOPRD1,OPRD2
该指令进行两个操作数的相减,即从OPRD1中减去OPRD2,其结果放于OPRD1中。具体地说,可以从累加器中减去立即数;
或从寄存器和内存操作数中减去立即数;或从寄存器操作数减去寄存器或内存操作数;或从寄存器或内存操作数减去寄存器操作数等,
其类型完全与ADD指令的相同,
例如:
SUB CX,BX
SUB [BP+2],CL
(2) SBB指令
该指令与SUB相类似,只不过在两个操作数相减时,还应减去借位标志CF的当前值。与ADC一样,这条指令主要用于多字节的减法运算,在前面的四字节
加法运算的例子中,若用SUB代替ADD,用SBB代替ADC,那么就可以实现两个四字节的减法运算。该指令对标志位AF、CF、OF、PF、SF和ZF都将产生影响。
(3) DECOPRD指令
该指令实现对操作数的减1操作,所用的操作数可以是寄存器的,也可以是内存的。
在相减时,把操作数看作为无符号的二进制数。该指令执行结果将影响标志位AF、OF、PF、SF和ZF,但对CF标志不产生影响,
例如:
DEC BX
DEC [DI]
(4) NEG OPRD
该指令用来对操作数进行求补操作,即用零减去操作数,然后再将结果送回,
例如:
NEG AL
NEG MULRE
该指令对字节操作时,对-128求补;对字操作时,对-32768求补,则操作数不变,但是此时溢出标志OF将置位。
(5) CMPOPRD1,OPRD2
该指令为比较指令,完成OPRD1-OPRD2的操作,这一点与减法指令相同,而且相减结果也同样反映在标志位上。但是与减法指令SUB的主要不同点是相减后
不回送结果,即执行比较指令以后,两个操作数的内容是不变化的。
比较指令可以用于累加器与立即数,累加器与任一通用寄存器或任一内存操作数之间的比较。
例如:
CMP AL,100
CMPAX,SI
CMPAX,DATA[BX]
该指令也可以用于任一寄存器与立即数或别的寄存器及任一内存操作数之间的比较,
例如:
CMP BX,04FEH
CMP DX,DI
CMP CX,COUNT[BP]
该指令还可以用于内存操作数与立即数及任一寄存器中操作数之间的比较,
例如:
CMP DATA,100
CMP COUNT[SI],AX
CMP POINTER[DI],BX
综上所述,可以归纳出如下结论:
当没有溢出时(OF=0),若SF=0,则AX≥BX;若SF=1,则AX
当产生溢出时(OF=1),若SF=0,则AX
用逻辑表达式又可简化为:
若OFSF=0,则AX≥BX; ;
若OFSF=1,则AX
例如,若自BLOCK开始的内存缓冲区中,有100个带符号的数,希望找到其中最大的一个值,并将它放到MAX单元中。
编制该程序的思路是这样的:先把数据块中的第一个数取到AX中,然后从第二个存贮单元开始,依次与AX中的内容进行比较。若AX中的值大,则接着比较;
若AX中的值小,则把内存单元中的内容送到AX中。这样经过99次比较,在AX中必然存放着数据块中最大的一个数,然后利用传送指令将它放到MAX单元中去。
这是一个循环程序。循环程序开始应置初值,包括循环次数为99次。在循环体中应包括比较指令和转移控制指令。
满足上述功能要求的程序是:
MOV BX,OFFSET BLOCK
MOV AX,
INC BX
INC BX
MOV CX,99
AGAIN: CMP AX,[BX]
JG NEXT
MOV AX,[BX]
NEXT:INC BX
INC BX
DEC CX
JNE AGAIN
MOV MAX,AX
HLT
8088除了上述的算术运算指令以外,还有几条功能很强的乘、除法指令和校正指令。
3. 乘法指令
(1)无符号数乘法指令MUL
该指令的一般格式为MUL OPRD ;OPRD为源操作数
例:字节乘以字节:
MOVAL,LSRC --BYTE;被乘数送AL
MULRSRC --BYTE;结果存于AX中
字乘以字
MOV AX,LSRC –WORD ;一个字送AX
MUL RSRC –WORD ;结果的高字节在DX中;低字节在AX中
字节乘以字:
MOVAL,MUL –BYTE ;字节被乘数送AL
CBW ;AL中字节转换成AX中的字
MULRSRC --WORD ;
(2) 带符号数乘法指令IMUL
该指令的一般格式为IMULOPRD
例:字节乘以字节:
MOV AL,LSRC –BYTE ;被乘数送AL
IMUL RSRC --BYTE ;4. 除法指令
8088有两条除法指令:无符号除法指令和带符号除法指令。
(1)无符号数除法指令DIV
执行该指令,如果结果大于寄存器可以保存的值时,则产生0型中断。
例:字除以字节:
MOV AX,NUMERATOR –WORD ;被除数送AX
DIV DIVISOR –BYTE ;商在AL中,余数在AH中
字节除以字节:
MOVAL,NUMERATOR –BYTE ;被除数送AL
CBW ;AL中的字节扩展成AX中的字
DIV DIVISOR --BYTE
字除以字:
MOV AX,NUMERATOR --WORD
CWD ;把字转换成双字DX、AX
DIVDIVISOR –WORD ;商在AX中,余数在DX中
(2) 带符号除法指令IDIV
该指令是带符号的除法指令。除后,余数符号与被除数相同,其它同DIV指令。该指令一般格式为IDIVOPRD
例:双倍字长除以字:
MOVDX,NUM --HI –WORD ;被除数高位字送DX
MOVAX,NUM --LO –WORD ;被除数低位字送AX
IDIVDIVISOR --WORD[SI]
5.校正指令
8088的调整指令主要用于十进制数的调整。
AAA——对AL中ASCII未压缩的十进制和进行调整;
AAS——对AL中ASCII未压缩的十进制差进行调整;
AAD——在除法指令前对AX中ASCII未压缩的十进制数进行调整;
AAM——对AX中两个ASCII未压缩十进制相乘结果进行调整;
DAA——对AL中的两个压缩十进制数相加之和进行调整,得到压缩十进制和;
DAS——对AL中的两个压缩十进制数相减之差进行调整,得到压缩十进制差