乘除运算指令
8086/8088除了提供加减运算指令外,还提供乘除运算指令。乘除运算指令分为无符号数运算指令和有符号数运算指令,这点与加减指令不同。乘除运算指令对标志位的影响有些特别,不像加减运算指令对标志位的影响那样自然。
1.乘法指令
在乘法指令中,一个操作数总是隐含在寄存器AL(8位数相乘)或者AX(16位数相乘)中,另一个操作数可以采用除了立即数方式以外的任一种寻址方式。
(1)无符号数乘法指令MUL
无符号指令的格式如下:
MUL OPRD
如果OPRD是字节操作数,则把AL中的无符号数与OPRD相乘,16位结果送到AX中;如果OPRD是字操作数,则把AX中的无符号数与OPRD相乘,32位结果送到DX和AX对中,DX含高16位,AX含低16位。所以由操作数OPRD决定是字节相乘还是字相乘,例如:
MUL BL
MUL AX
MUL VARW ;VARW是字变量
如果乘积结果的高半部分(字节相乘时为AH,在字相乘时位DX)不等于零,则标志CF=1,OF=1;否则CF=0,OF=0。所以如果CF=1和OF=1表示在AH或者DX中含有结果的有效数。该指令对其他标志位无定义。
(2)有符号数乘法指令IMUL
有符号数乘法指令格式如下:
IMUL OPRD
这条指令把乘数和被乘数均作为有符号数,此外与指令MUL完全类似。例如:
IMUL CL
IMUL DX
IMUL VARW ;VARW是字变量
如果乘积结果的高半部分(字节相乘时为AH,在字相乘时DX)不是低半部分的符号扩展,则CF=1,OF=1;否则CF=0,CF=0。所以如果CF=1和OF=1表示在AH或DX中含有结果的有效数。该指令对其他标志位无定义。
2.除法指令
在除法指令中,被除数总是在隐含在寄存器AX(除数是8位)或者DX和AX(除数是16位)中,另一个操作数可以采用除了立即数外的任意一种寻址方式。
(1)无符号数除法指令DIV
无符号数除法指令的格式如下:
DIV OPRD
如果OPRD是字节操作数,则把AX中的无符号数除以OPRD,8位的商送到AL中,8位的余数送到AH;如果OPRD是字操作数,则把DX(高16位)和AX中的无符号数除以OPRD,16位的商送到AX,16位的余数送到DX中。所以由操作数OPRD决定是字节除,还是字除。例如:
DIV BL
DIV SI
DIV VARW ;VARW是字变量
注意:如果除数为0,或者在8位数除时商超过8位,或者在16位除时商超过16位,则认为是除溢出,引起0号中断。
除法指令对标志位的影响无定义。
(2)有符号数除法指令IDIV
有符号数除法指令格式如下:
IDIV OPRD
这条指令把被除数和除数均作为有符号数,此外与DIV完全类似。
例如:
IDIV CX
IDIV VARW ;VARW是字变量
如果除数为0,或者商太大(字节除时超过127,字除时超过32767),或者商太小(字节除时小于-127,字除时小于-32767)时,则引起0号中断。
3.符号扩展指令
由于除法指令隐含使用字被除数或双字被除数,所以当被除数为字节,或者除数和被除数均为字时,需要在除操作前扩展被除数。为此8086/8088专门提供了符号扩展指令。
(1)字节转换为字指令CBW(Convert Byte to Word)
字节转换为字指令的格式如下:
CBW
这条指令把寄存器AL中的符号扩展到寄存器AH。即若AL的最高有效位为0,则AH=0;若AL的最高有效位为1,则AH=0FFH。例如:
MOV AX,3487H ;AX=3487H,即AH=34H,AL=87H
CBW ;AH=0FFH,AL=87H,即AX=0FF87H
这条指令能在两个字节相除以前,产生一个字长度的被除数。这条指令不影响各标志位。
(2)字转换为双字指令CWD(Convert Word to Double word)
字转换为双字指令格式如下:
CWD
这条指令把寄存器AX中的符号扩展到寄存器DX。即若(AX)的最高有效位为0,则DX=0;若AX的最高有效位为1,则DX=0FFFFH。
例如:
MOV AX,4567H ;AX=4567H
CWD ;AX=4567H,DX=0
这条指令能在两个字相除以前,产生一个双字长度的被除数。该指令不影响各标志位。
逻辑运算和位移指令
这组指令包括逻辑运算,位移和循环移位指令三部分。逻辑运算指令除NOT外,均有两个操作数。位移和循环移位指令只有一个操作数。关于这组指令有如下几点说明,请予以注意:
(1)如果指令有两个操作数,最多只能有一个位存储器操作数。
(2)只有通用寄存器或存储其操作数可以作为目的操作数,用于存放运算结果。
(3)如果只有一个操作数,则该操作数即是源又是目的。
(4)操作数可以是字节,也可以是字。但如果有两个操作数,则他们的类型必须一致。即同为字节或者同为字。
(5)对于存储器操作数可采用四种标准存储器操作数寻址方式。
1.逻辑运算指令
(1)否操作指令NOT
否操作指令的格式如下:
NOT OPRD
这条指令把操作数OPRD取反,然后送回OPRD
例如:
NOT AX
NOT VARB ;VARB是字节变量
操作数OPRD可以是通用寄存器,也可以是存储器操作数。此指令对标志没有影响。
(2)与操作指令AND
与操作指令格式如下:
AND OPRD1,OPRD2
这条指令对两个操作数进行按位的逻辑“与”运算,结果送到目的操作数OPRD1.
例如:
AND DH,DH
AND AX,ES:[SI]
该指令执行以后,标志CF=0,标志OF=0,标志PF,ZF,SF反映运算结果,标志AF未定义。
某个操作数自己与自己相“与”,则值不变,但可使进位标志CF清0.与操作指令主要用在使一个操作数中的若干位维持不变,而另外若干位清0的场合。把要维持不变的这些位与“1”相“与”,二要把清位0的这些位与“0”相“与”就能达到目的。
例如:
MOV AL,34H ;AL = 34H
AND AL,0FH ;AL = 04H
(3)或操作指令OR
或操作指令的格式如下:
OR OPRD1,OPRD2
这条指令对两个操作数进行按位的逻辑“或”运算,结果送到操作数OPRD1。
例如:
OR AX,8080H
OR CL,AL
OR [BX-3],AX
OR指令执行以后,标志CF=0,标志OF=0,标志PF,ZF,SF反映运算结果,标志AF未定义。
某个操作数自己与自己相“或”,则值不变,但可使进位标志CF清0.或操作指令主要用在使一个操作数中的若干位维持不变,而另外若干位置为1的场合。把要维持不变的这些位与“0”相“或”,而把要置为1的这些位与“1”相“或”,就能达到这样的目的。
例如:
MOV AL,41H ;AL=01000001B,B表示二进制
OR AL,20H ;AL=01100001B
(4) 异或操作指令XOR
XOR OPRD1,OPRD2
这条指令对两个操作数进行按位的逻辑“异或”运算,结果送到目的操作数OPRD1。该指令执行以后,标志CF= 0,标志OF=0,标志PF,ZF,SF反映运算结果,标志AF未定义。
某个操作数自己与自己相“异或”,则结果位0,并可使进位标志CF清0,例如:
XOR DX,DX ;DX=0,CF=0
异或操作指令主要在使一个操作数中的若干位维持不变,而另外若干位置取反的场合。把要维持不变的这些位与“0”相“异或”,而把要取反的这些位与“1”相“异或”就能达到这样的目的。例如:
MOV AL,34H ;AL=00110100B,符号表示二进制
XOR AL,0FH ;AL=00111011B
(5)测试指令 TEST
测试指令格式如下:
TEST OPRD1,OPRD2
这条指令和指令AND类似,也把两个操作数进行按位“与”,但结果不送到操作数OPRD1,仅仅影响标志位。该指令执行以后,标志ZF,PF和SF反映运算结果,标志CF和OF被清0。
该指令通常用于检测某些位是否为1,但又不希望改变原操作数值的场合。例如:要检查AL中的位6或位2是否有一位为1,可以使用如下指令:
TEST AL,01000100B
如果位6和位2全为0,那么在执行上面的指令后,ZF被置1,否则被清0。
2.一般移位指令
8086/8088有三条一般移位指令:算数左移/逻辑左移指令,算数右移指令,逻辑右移指令。这三条指令的一般格式如下:
SAL OPRD,m ;算术左移指令
SHL OPRD,m ;逻辑左移指令
SAR OPRD,m ;算术右移指令
SHR OPRD,m ;逻辑右移指令
其中,m是移位位数,或为1或为CL,当要移多个位时,移位位数需存放在CL寄存器中。操作数OPRD可以是通用寄存器,也可以是存储器操作数。
标志PF,SF和ZF反映移位后的结果。标志OF也受影响,但标志AF未定义。
(1)算数左移或逻辑左移指令SAL/SHL
算术左移和逻辑左移进行相同的动作,尽管为了方便提供有两个助记符,但只有一条机器指令。具体格式如下:
SAL OPRD,m
SHL OPRD,m
算术左移SAL/逻辑左移SHL,指令操作数OPRD左移m位,每移动一位,右边用0补足一位,移出的最高位进入标志位CF。
下面的程序片段用于说明该指令的使用及其对标志位的影响。
MOV AL,8CH ;AL=8CH
SHL AL,1 ;AL=18H,CF=1,PF=1,ZF=0,SF=0,OF=0
MOV CL,6 ;CL=6
SHL AL,CL ;AL=0,CF=0,PF=1,ZF=1,SF=0,OF=0
只要左移以后结果未超出一个字节或一个字的表达式范围,那么每左移一次,原操作数每一位的权增加一倍,也即相当于原数乘2.下面的程序片段实现把寄存器AL中的内容乘10,结果存放在AX中。
XOR AH,AH ;(AH)= 0
SHL AX,1 ;2X
MOV BX,AX ;暂存2X
SHL AX,1 ;4X
SHL AX,1 ;8X
ADD AX,BX ;8X+2X
(2)算术右移指令SAR
算术右移指令的格式如下:
SAR OPRD,m
该指令使操作数右移m位,同时每移一位,左边的符号位保持不变,移出的最低位进入标志位CF。例如:
SAR AL,1
SAR BX,CL
对于有符号和无符号数而言,算术右移一位相当于除以2。
(3)逻辑右移指令SHR(Shift logic Right)
逻辑右移指令格式如下:
SHR OPRD,m
该指令使操作数右移m位,同时每移一位,左边用0补足,移出的最低位进入标志位CF。例如:
SHR BL,1
SHR AX,CL
对于无符号数而言,逻辑右移一位相当于除以2。
在汇编语言程序设计中,经常需要对位为单位的数据进行合并和分解处理,一般通过移位指令和逻辑运算指令进行这种数据的合并和分解处理。
例,假设DATA1和DATA2各长4位,分别放在AL寄存器的低4位和高4位中,现要把他们分别存放在BL寄存器和BH寄存器的低4位中。
下面程序片段能够实现上述要求:
.......
MOV BL,AL
AND BL,0FH ;得DATA1
MOV BH,AL ;得DATA2
MOV CL,4
SHR BH,CL
........
3.循环移位指令
8086/8088有四条循环移位指令:左循环移位指令ROL(Rotate Left),右循环移位指令ROR(Rotate Right),带进位左循环移位指令RCL(Rotate Left through CF),带进位右循环移位指令RCR(Rotate Right through CF)。这些指令可以一次只移一位,可以一次移多位。如移多位,那么移位次数存放在CL寄存器中。
这些指令的格式如下:
ROL OPRD,m
ROR OPRD,m
RCL OPRD,m
RCR OPRD,m
其中,m是移位次数,或为1或为CL,操作数OPRD可以是通用寄存器,也可以是存储器操作数。
前两条循环指令没有把进位标志位CF包含在循环的环中;后两条循环指令把进位标志CF包含在循环的环中,即作为整个循环的一部分。
这些指令只影响标志CF和OF。
左循环移位指令ROL,它每移位一次,操作数左移,其最高位移入最低位。同时最高位也移入进位标志CF。