汇编语言03:8086算术运算指令

目录

进位标志CF

溢出标志OF

其他状态标志

加法指令

加法指令ADD

带进位加法指令ADC

增量指令INC

减法指令

减法指令SUB

带借位减法指令SBB

减量指令DEC

求补指令NEG

比较指令CMP

乘法指令

无符号数乘法指令MUL

有符号乘法指令IMUL

除法指令

无符号数二进制除法指令DIV

有符号数二进制除法指令IDIV

符号扩展指令

8位扩展指令CB(byte)W(word)

16位扩展指令CW(word)D(doubleword)

十进制调整指令

压缩BCD码调整指令DAA、DAS

非压缩BCD码调整指令

加和调整指令AAA

减差调整指令AAS

乘积调整指令AAM

除法调整指令AAD

总结:

8086的算术运算指令除了常见的加、减、乘、除指令,还有符号拓展指令和十进制调整指令。同时,在讨论算术运算指令时,我们需要仔细考虑状态标志带来的影响。

进位标志CF

首先是进位标志CF,它指示字节最高位是否产生进位。注意,在字节内产生进位不影响CF。例如如下二进制加法:

00011000+01111100 = [0]10010100

由于最高位没有继续向上进位,因此CF=0,但是如果是如下情况:

10011000+01111100 = [1]00010100

最高位继续向上进位,因此CF=1。

溢出标志OF

溢出标志用于表示有符号整数加减运算的结果是否超出了范围。若超出范围,则是有溢出,设置OF=1,否则OF=0。例如如下有符号运算:

00111010+0111100 = 10110110 (58+124=182)

运算结果发生了溢出,所以OF是1,实际上表达的是负数。10101010按照负数补码+1得到绝对值86,故这个数是-86。他和二进制数124相加,结果发生了进位,但是由于是有符号整数相加,不考虑进位,因此结果表现为38.

由上可以看出,进位标志CF和溢出标志OF作用的地方不相同。其中,CF用于判断无符号整数运算结果是否超出范围,而溢出标志表示有符号整数运算结果是否超出范围。实际上,在使用汇编语言进行编程时,标志的控制方面是需要程序员注意的。

其他状态标志

1.零标志ZF反映运算结果是否为0。注意,产生进位的情况不在该标志的考虑范围内。例如如下二进制加法

11111111+00000001 = [1]00000000.

此时进位标志CF被设置为1,但同时地零标志ZF也会被设置为1,表示运算结果是0.

2.符号标志SF反映运算结构是正数还是负数。可以通过符号位来判断。

3.奇偶标志PF并非判断结果是奇数还是偶数,而是反映运算结果最低字节中‘1’的个数是偶数还是奇数,从而实现奇偶校验。若个数是偶数个,则PF=1,否则PF=0。

4.调整标志AF反映加减运算时最低半字节有无进位或者借位.当有进(借)位时,将AF设置为1,否则设置为0.

总结了以上运算时可能遇到的标志之后,接下来介绍算术运算指令。、

加法指令

8086提供了三种加法指令:

加法指令ADD

操作:将源操作数与目的操作数相加,结果送目的操作数。其基本格式如下:

ADD reg,imm/reg/mem
ADD mem,imm/reg

寻址方式:和其他指令相同,源操作数和目的操作数不可以同时是存储器的存储单元。

标志影响:对OF,SF,ZF,AF,PF,CF造成影响。

带进位加法指令ADC

操作:在执行ADD指令的同时加上进位标志CF。主要用于和ADD指令一起完成多精度数相加。其基本格式如下:

ADC reg,imm/reg/mem
ADC mem,imm/reg

寻址方式:和其他指令相同,源操作数和目的操作数不可以同时是存储器的存储单元。

标志影响:ADC用在下位进位的加法中,在运算时将会在除最低字节考虑CF的影响。例如,若操作数值分别为0001H和0002H,CF=1,那么得出结果将会是0005H。

增量指令INC

操作:只有一个操作数,对操作数加1。其基本格式如下:

INC reg/mem

寻址方式:因为为自增,不能为立即数寻址。

标志影响:不影响CF,其他情况和ADD,ADC一样。

从汇编指令可以看出,这是高级语言中运算符+和++(C语言)的雏形和底层。

减法指令

减法指令执行字或者字节的减法运算。常用的减法指令有SUB,SBB,DEC,NEG,CMP

减法指令SUB

操作:执行减法指令,结果送目的操作数,类似于ADD指令。其基本格式如下:

SUB reg,reg/mem/imm
SUB mem,reg/imm

寻址方式:和其他指令相同,源操作数和目的操作数不可以同时是存储器的存储单元。

标志影响:影响OF,SF,PF,CF,ZF,AF.

带借位减法指令SBB

操作:在执行SUB的基础上,如果CF为1,还需要再减去1。其基本格式如下:

SBB reg,imm/reg/mem
SBB mem,imm/reg

寻址方式:和其他指令相同,源操作数和目的操作数不可以同时是存储器的存储单元。该指令常用于和SUB结合来进行多精度的减法。

标志影响:用在下位借位的减法中,一般会在除最低字节外考虑CF的影响。

减量指令DEC

操作:只有一个操作数,对操作数-1.其基本格式如下:

DEC reg/mem

寻址方式:因为为自减,不能为立即数寻址。

标志影响:不影响CF,其他情况和SUB,SBB一样。

求补指令NEG

操作:对操作数按位取反后加1.当操作数是有符号数时,求补指令作用为求其相反数。其基本格式如下:

NEG reg/mem

寻址方式:因为为求反,不能为立即数寻址。

标志影响:和SUB一样。

比较指令CMP

操作:将目的操作数减去源操作数,但是结果不返回。即:只会影响标志,不会影响操作数。一般用于流程的控制,比如条件和循环判断。其基本格式如下:

CMP reg,imm/reg/mem
CMP mem,imm/reg

寻址方式:和其他指令相同,源操作数和目的操作数不可以同时是存储器的存储单元。

影响标志:和SUB一样。

下方展示了一个比较和返回的简单代码:

CMP AL,100          ;AL-100
JB below            ;AL<100,跳转到below执行
SUB AL,100            ;AL<-AL-100
INC AH                ;AJ<-AH+1
below:

从产生效果来看,减法指令是高级语言中 -, --(C语言),>,<的底层之一。

乘法指令

乘法指令包括无符号数乘法指令MUL和有符号数乘法指令IMUL。

无符号数乘法指令MUL

操作:MUL是单操作数指令,其隐含的目的操作数是AX。其基本格式如下:

MUL r8/m8        ;AX<-AX*r8/m8
MUL r16/m16        ;AX<-AX*r16/m16

如果是字节量相乘,则AL与r8/m8得到16位的字,存入AX中;若是16位数据相乘,则AX与r16/m16相乘,得到32位结果,其高字存入DX,低字节存入AX中。

寻址方式:寄存器寻址或者主存寻址。

标志影响:对OF和CF有影响。若乘积的高一半(比如字节乘法的AH)不含有有效数值,那么OF=CF=0。否则OF=CF=1。

不同于没有影响,乘法指令对其他标志的影响是未定义的。

下面是一个展示无符号数计算和存储的简单过程。

MOV AL,0B4H
MOV BL,11H
MUL BL        ;将结果0BF4H送AX,OF=CF=1(AH不为0)
有符号乘法指令IMUL

操作:IMUL是单操作数指令,其隐含的目的操作数是AX。其基本格式如下:

IMUL r8/m8
IMUL r16/m16

寻址方式:同MUL指令。

标志影响:同MUL指令。

注意,同一操作数在不同的指令下,结果可能是不同的。如果将无符号数存储和计算过程中的MUL指令换成IMUL指令,那么计算结果将会是FAF4H(这是因为最高位被当成了符号位导致的)。

除法指令

和乘法指令相同,除法指令分为无符号二进制除法指令DIV和有符号二进制数除法指令IDIV两种。

无符号数二进制除法指令DIV

操作:DIV是单操作数指令,其隐含的源操作数是AX。注意,进行的操作是二进制除法。其基本格式如下:

DIV r8/m8        ;AX<-AX/r8(m8)
DIV r16/m16        ;AX<-AX/r16(m16)

当时字节除法,将8位商送AL,8位余数存入AH。如果是16位字除法,16位商存入AX,16位余数存入DX。余数的符号和被除数相同。

寻址方式:寄存器寻址或者主存寻址。

标志影响:DIV指令对标志的影响没有定义。但是除法却有可能产生溢出。这种情况是因为被除数远大于除数导致的。在DIV指令中,当做字节除法时,默认被除数是AX;当做字除法时,默认被除数是DX、AX组成的32位。如果存放商的寄存器AL/AX不能表达,便产生溢出。CPU此时会产生编号为0的内部终端。而操作系统只提示出错。下面是一个溢出的例子:

MOV AX FFF0H
MOV BL 02H;
DIV BL    ;进行字节除法,结果得到7778H,超出字节表达范围

另外,在除数为0时,一样会产生溢出。

有符号数二进制除法指令IDIV

IDIV指令的大致操作、寻址方式和DIV指令相同,在此不做赘述。

符号扩展指令

8086处理器在进行指令时一般要求两个操作数类型一致,但是实际的数据类型不一定满足要求,例如一定要将8位和16位加减运算,这时需要先进行扩展,转换成相同位数据然后进行运算。符号扩展指令就是应对上述情况而产生的。

对无符号数据,只要在前面加0就实现了位数扩展且大小不变,这叫做0位扩展。而对于有符号数据,由于存在负数(补码)表示的问题,需要进行符号拓展。符号扩展的规则是:当是正数的情况下,和无符号数一样实行0位扩展;当是负数时,因为补码表示的缘故,为不影响数据大小,将高位全部填充为1。

假设有8位无符号数据64H(100)需要位数扩展,那么位数扩展之后的16位数据为0064H,使用了0位扩展。另有16位有符号数据FF00H(-256)需要位数扩展,那么位数扩展之后的32位数据是FFFF FF00H,使用了符号扩展。

8位扩展指令CB(byte)W(word)

操作:CBW不带其他操作数,其将AL的最高有效位D7扩展到D15。如果有效位是0,那么AH=00;否则为FF。

寻址方式:操作数固定为AL。

标志影响:无。

16位扩展指令CW(word)D(doubleword)

操作:CBW不带其他操作数,其将AX的最高有效位D15扩展到DX。

寻址方式:操作数固定为AX。

标志影响:无。

考虑以下无符号数减法:

得到的结果为FFFD F6F6H。

上面的扩展说明:当高位全是符号扩展时,实际上截断高位不影响计算结果。因此在进行乘法指令时,通过CF和OF可以判断是否可以截断高位而不影响实际结果。

十进制调整指令

上述运算指令都是二进制计算,但是如果需要实际上进行实际计算,则需要进行十进制调整指令。通过第一章我们知道,实际上计算机内十进制使用(压缩)BCD码表示。

压缩BCD码调整指令DAA、DAS

操作:对AL的二进制结果进行十进制调整。由于在不同的运算中二进制和十进制实际存在差异,使用DAA(addition)进行加和的十进制调整,使用DAS(substitution)进行减差的十进制调整。其基本格式如下:

DAA        ;对AL中的加和进行十进制调整
DAS        ;对AL中的减差进行十进制调整

寻址方式:操作数固定为AL。

标志影响:对OF标志无定义,并且根据操作结果影响其他所有标志。其中CF反映加减的进(借)位状态。

下面给出一个加和例子。

MOV AL,68H
MOV BL,28H
ADD AL,BL        ;AL<-90H
DAA        ;AL<-96H,反映68+28=96.CF=0
非压缩BCD码调整指令

非压缩BCD码用一个字节表示一个十进制位,通常低四位表示有效数字,高四位任意但是通常为0。与压缩BCD码不同,非压缩BCD码调整指令还提供了乘法、除法的十进制调整指令。

加和调整指令AAA

操作:一般跟随在AL为目的操作数的ADD或者ADC之后,对AL进行非压缩BCD码调整。

寻址方式:操作数固定为AL。

标志影响:如果产生了进位,则将进位1加到AH中,同时CF=AF=1。否则CF=AF=0。对其他标志无定义。

下面给出一个非压缩BCD码的加法运算:

MOV AX,0608H         ;AX<-68
MOV BL,09H        ;BX<-9
ADD AL,BL       ;AX = 0611H
AAA            ;AX=0707H,CF=AF=1

产生了进位时,可以看到AH的06变成了07,同时AL的高四位被清零,AL的低四位加6.

减差调整指令AAS

操作:一般跟随在AL为目的操作数的SUB或者SBB之后,对AL进行非压缩BCD码调整。

寻址方式:操作数固定为AL。

标志影响:如果产生了借位,则将借位1加到AH中,同时CF=AF=1。否则CF=AF=0。对其他标志无定义。

同时,该指令一样将AL的高四位清零。

乘积调整指令AAM

操作:AAM一般跟随在以AX为目的操作数(8位乘法)的MUL指令后,对AX进行非压缩BCD码调整。利用MUL相乘的两个非压缩BCD码的高四位必须为0。

寻址方式:操作数固定为AX.

标志影响:根据结果设置SF,ZF和PF。但是OF,AF,CF无定义。

下面给出一个非压缩BCD码的乘法运算。

MOV AX,0608H
MOV BL,09H
MUL BL
AAM        ;AX=0702H,->8*9=72

注意,AX的结果只反映了AL和BL的乘积,AX的高8位被截断了。

除法调整指令AAD

操作:AAD先将存放在AX寄存器中的两位非压缩BCD码进行调整,再用DIV除以一个非压缩BCD数。即和其他指令先运算再调整相反。其中,要求AL,AH和除数的高四位为0,否则将产生错误。

寻址方式:操作数固定为AX。

标志影响:和AAM相同,根据结果设定SF,ZF和PF,但是对OF,CF,AF无定义。

下面给出一个非压缩BCD码除法的例子。

MOV AX 0608H
MOV BL,09H
AAD         ;AX = 0044H,对应十进制数68
DIV BL        ;AL=07H,AH=05H
;实现除法68/9 = 7 ……5

总结:

算术运算指令是汇编语言的核心指令之一,根据不同的使用情况设置了多种四则运算指令,并且设置了辅助的符号扩展指令和十进制调整指令。使用时需要不仅需要记忆寄存器和主存的结果,更要关注符号标志对运算结果的影响。在运算指令中存在迭代和流程控制的INC,DEC和CMP指令,他们的使用方法也值得关注。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值