8086/8088汇编指令系统剖析(三)

时间:2021-04-10 00:43:47

 

乘除运算指令

 

 

 

8086/8088除了提供加减运算指令外,还提供乘除运算指令。乘除运算指令分为无符号数运算指令和有符号数运算指令,这点与加减指令不同。乘除运算指令对标志位的影响有些特别,不像加减运算指令对标志位的影响那样自然。

 

 

 

1.乘法指令

 

 

 

在乘法指令中,一个操作数总是隐含在寄存器AL8位数相乘)或者AX16位数相乘)中,另一个操作数可以采用除了立即数方式以外的任一种寻址方式。

 

1)无符号数乘法指令MUL

 

无符号指令的格式如下:

 

 

 

MUL OPRD

 

 

 

如果OPRD是字节操作数,则把AL中的无符号数与OPRD相乘,16位结果送到AX中;如果OPRD是字操作数,则把AX中的无符号数与OPRD相乘,32位结果送到DXAX对中,DX含高16位,AX含低16位。所以由操作数OPRD决定是字节相乘还是字相乘,例如:

 

 

 

MUL BL

 

MUL AX

 

MUL VARW VARW是字变量

 

 

 

如果乘积结果的高半部分(字节相乘时为AH,在字相乘时位DX)不等于零,则标志CF=1OF=1;否则CF=0OF=0。所以如果CF=1OF=1表示在AH或者DX中含有结果的有效数。该指令对其他标志位无定义。

 

 

 

2)有符号数乘法指令IMUL

 

有符号数乘法指令格式如下:

 

 

 

IMUL OPRD

 

 

 

这条指令把乘数和被乘数均作为有符号数,此外与指令MUL完全类似。例如:

 

 

 

IMUL CL

 

IMUL DX

 

IMUL VARW VARW是字变量

 

 

 

如果乘积结果的高半部分(字节相乘时为AH,在字相乘时DX)不是低半部分的符号扩展,则CF=1OF=1;否则CF=0CF=0。所以如果CF=1OF=1表示在AHDX中含有结果的有效数。该指令对其他标志位无定义。

 

 

 

2.除法指令

 

在除法指令中,被除数总是在隐含在寄存器AX(除数是8位)或者DXAX(除数是16位)中,另一个操作数可以采用除了立即数外的任意一种寻址方式。

 

 

 

1)无符号数除法指令DIV

 

无符号数除法指令的格式如下:

 

 

 

DIV OPRD

 

 

 

如果OPRD是字节操作数,则把AX中的无符号数除以OPRD8位的商送到AL中,8位的余数送到AH;如果OPRD是字操作数,则把DX(高16位)和AX中的无符号数除以OPRD16位的商送到AX16位的余数送到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)字节转换为字指令CBWConvert Byte to Word

 

字节转换为字指令的格式如下:

 

 

 

CBW

 

 

 

这条指令把寄存器AL中的符号扩展到寄存器AH。即若AL的最高有效位为0,则AH=0;若AL的最高有效位为1,则AH=0FFH。例如:

 

 

 

MOV AX3487H AX=3487H,即AH=34HAL=87H

 

CBW AH=0FFHAL=87H,即AX=0FF87H

 

 

 

这条指令能在两个字节相除以前,产生一个字长度的被除数。这条指令不影响各标志位。

 

 

 

2)字转换为双字指令CWDConvert Word to Double word

 

字转换为双字指令格式如下:

 

 

 

CWD

 

 

 

这条指令把寄存器AX中的符号扩展到寄存器DX。即若(AX)的最高有效位为0,则DX=0;若AX的最高有效位为1,则DX=0FFFFH

 

 

 

例如:

 

 

 

MOV AX4567H AX=4567H

 

CWD AX=4567HDX=0

 

 

 

这条指令能在两个字相除以前,产生一个双字长度的被除数。该指令不影响各标志位。

 

 

 

 

 

逻辑运算和位移指令

 

 

 

这组指令包括逻辑运算,位移和循环移位指令三部分。逻辑运算指令除NOT外,均有两个操作数。位移和循环移位指令只有一个操作数。关于这组指令有如下几点说明,请予以注意:

 

 

 

1)如果指令有两个操作数,最多只能有一个位存储器操作数。

 

2)只有通用寄存器或存储其操作数可以作为目的操作数,用于存放运算结果。

 

3)如果只有一个操作数,则该操作数即是源又是目的。

 

4)操作数可以是字节,也可以是字。但如果有两个操作数,则他们的类型必须一致。即同为字节或者同为字。

 

5)对于存储器操作数可采用四种标准存储器操作数寻址方式。

 

 

 

1.逻辑运算指令

 

 

 

1)否操作指令NOT

 

否操作指令的格式如下:

 

 

 

NOT OPRD

 

 

 

这条指令把操作数OPRD取反,然后送回OPRD

 

例如:

 

 

 

NOT AX

 

NOT VARB VARB是字节变量

 

 

 

操作数OPRD可以是通用寄存器,也可以是存储器操作数。此指令对标志没有影响。

 

 

 

2)与操作指令AND

 

与操作指令格式如下:

 

 

 

AND OPRD1OPRD2

 

 

 

这条指令对两个操作数进行按位的逻辑“与”运算,结果送到目的操作数OPRD1.

 

例如:

 

 

 

AND DHDH

 

AND AXES[SI]

 

 

 

该指令执行以后,标志CF=0,标志OF=0,标志PFZFSF反映运算结果,标志AF未定义。

 

某个操作数自己与自己相“与”,则值不变,但可使进位标志CF0.与操作指令主要用在使一个操作数中的若干位维持不变,而另外若干位清0的场合。把要维持不变的这些位与“1”相“与”,二要把清位0的这些位与“0”相“与”就能达到目的。

 

 

 

例如:

 

 

 

MOV AL34H AL = 34H

 

AND AL0FH AL = 04H

 

 

 

3)或操作指令OR

 

或操作指令的格式如下:

 

 

 

OR OPRD1OPRD2

 

 

 

这条指令对两个操作数进行按位的逻辑“或”运算,结果送到操作数OPRD1

 

例如:

 

 

 

OR AX8080H

 

OR CLAL

 

OR [BX-3]AX

 

 

 

OR指令执行以后,标志CF=0,标志OF=0,标志PFZFSF反映运算结果,标志AF未定义。

 

某个操作数自己与自己相“或”,则值不变,但可使进位标志CF0.或操作指令主要用在使一个操作数中的若干位维持不变,而另外若干位置为1的场合。把要维持不变的这些位与“0”相“或”,而把要置为1的这些位与“1”相“或”,就能达到这样的目的。

 

例如:

 

 

 

MOV AL41H AL=01000001BB表示二进制

 

OR AL20H AL=01100001B

 

 

 

4) 异或操作指令XOR

 

 

 

XOR OPRD1OPRD2

 

 

 

这条指令对两个操作数进行按位的逻辑“异或”运算,结果送到目的操作数OPRD1。该指令执行以后,标志CF= 0,标志OF=0,标志PFZFSF反映运算结果,标志AF未定义。

 

 

 

某个操作数自己与自己相“异或”,则结果位0,并可使进位标志CF0,例如:

 

 

 

XOR DXDX DX=0CF=0

 

 

 

异或操作指令主要在使一个操作数中的若干位维持不变,而另外若干位置取反的场合。把要维持不变的这些位与“0”相“异或”,而把要取反的这些位与“1”相“异或”就能达到这样的目的。例如:

 

 

 

MOV AL34H AL=00110100B,符号表示二进制

 

XOR AL0FH AL=00111011B

 

 

 

5)测试指令 TEST

 

测试指令格式如下:

 

 

 

TEST OPRD1OPRD2

 

 

 

这条指令和指令AND类似,也把两个操作数进行按位“与”,但结果不送到操作数OPRD1,仅仅影响标志位。该指令执行以后,标志ZFPFSF反映运算结果,标志CFOF被清0

 

该指令通常用于检测某些位是否为1,但又不希望改变原操作数值的场合。例如:要检查AL中的位6或位2是否有一位为1,可以使用如下指令:

 

 

 

TEST AL01000100B

 

如果位6和位2全为0,那么在执行上面的指令后,ZF被置1,否则被清0

 

 

 

2.一般移位指令

 

 

 

8086/8088有三条一般移位指令:算数左移/逻辑左移指令,算数右移指令,逻辑右移指令。这三条指令的一般格式如下:

 

 

 

SAL OPRDm ;算术左移指令

 

SHL OPRDm ;逻辑左移指令

 

SAR OPRDm ;算术右移指令

 

SHR OPRDm ;逻辑右移指令

 

 

 

其中,m是移位位数,或为1或为CL,当要移多个位时,移位位数需存放在CL寄存器中。操作数OPRD可以是通用寄存器,也可以是存储器操作数。

 

标志PFSFZF反映移位后的结果。标志OF也受影响,但标志AF未定义。

 

1)算数左移或逻辑左移指令SAL/SHL

 

 

 

算术左移和逻辑左移进行相同的动作,尽管为了方便提供有两个助记符,但只有一条机器指令。具体格式如下:

 

 

 

SAL OPRDm

 

SHL OPRDm

 

 

 

算术左移SAL/逻辑左移SHL,指令操作数OPRD左移m位,每移动一位,右边用0补足一位,移出的最高位进入标志位CF

 

下面的程序片段用于说明该指令的使用及其对标志位的影响。

 

 

 

MOV AL8CH AL=8CH

 

SHL AL1 AL=18HCF=1PF=1ZF=0SF=0OF=0

 

MOV CL6 CL=6

 

SHL ALCL AL=0CF=0PF=1ZF=1SF=0OF=0

 

 

 

只要左移以后结果未超出一个字节或一个字的表达式范围,那么每左移一次,原操作数每一位的权增加一倍,也即相当于原数乘2.下面的程序片段实现把寄存器AL中的内容乘10,结果存放在AX中。

 

 

 

XOR AHAH ;(AH= 0

 

SHL AX1 2X

 

MOV BXAX ;暂存2X

 

SHL AX1 4X

 

SHL AX1 8X

 

ADD AXBX 8X+2X

 

 

 

2)算术右移指令SAR

 

算术右移指令的格式如下:

 

SAR OPRDm

 

该指令使操作数右移m位,同时每移一位,左边的符号位保持不变,移出的最低位进入标志位CF。例如:

 

 

 

 

 

SAR AL1

 

SAR BXCL

 

 

 

对于有符号和无符号数而言,算术右移一位相当于除以2

 

 

 

3)逻辑右移指令SHRShift logic Right

 

逻辑右移指令格式如下:

 

 

 

SHR OPRDm

 

 

 

该指令使操作数右移m位,同时每移一位,左边用0补足,移出的最低位进入标志位CF。例如:

 

 

 

SHR BL1

 

SHR AXCL

 

 

 

对于无符号数而言,逻辑右移一位相当于除以2

 

 

 

在汇编语言程序设计中,经常需要对位为单位的数据进行合并和分解处理,一般通过移位指令和逻辑运算指令进行这种数据的合并和分解处理。

 

例,假设DATA1DATA2各长4位,分别放在AL寄存器的低4位和高4位中,现要把他们分别存放在BL寄存器和BH寄存器的低4位中。

 

 

 

下面程序片段能够实现上述要求:

 

 

 

.......

 

 

 

MOV BLAL

 

AND BL0FH ;得DATA1

 

MOV BHAL ;得DATA2

 

MOV CL4

 

SHR BHCL

 

........

 

 

 

3.循环移位指令

 

 

 

8086/8088有四条循环移位指令:左循环移位指令ROLRotate Left,右循环移位指令RORRotate Right,带进位左循环移位指令RCLRotate Left through CF,带进位右循环移位指令RCRRotate Right through CF)。这些指令可以一次只移一位,可以一次移多位。如移多位,那么移位次数存放在CL寄存器中。

 

 

 

这些指令的格式如下:

 

 

 

ROL OPRDm

 

ROR OPRDm

 

RCL OPRDm

 

RCR OPRDm

 

 

 

其中,m是移位次数,或为1或为CL,操作数OPRD可以是通用寄存器,也可以是存储器操作数。

 

前两条循环指令没有把进位标志位CF包含在循环的环中;后两条循环指令把进位标志CF包含在循环的环中,即作为整个循环的一部分。

 

 

 

这些指令只影响标志CFOF

 

 

 

左循环移位指令ROL,它每移位一次,操作数左移,其最高位移入最低位。同时最高位也移入进位标志CF