[汇编]8086指令系统---算术指令(二)

[汇编]8086指令系统---算术指令(二)

 4 除法指令

 DIV  src 无符号数除法(unsigned divide
 IDIV src 带符号数除法(signed divide
 字节操作: (AL) ← (AX) / src 的商
      (AH) ← (AX) / src 的余数
 字操作: (AX) ← (DX, AX) / src 的商
     (DX) ← (DX, AX) / src 的余数

  参加运算的除数和被除数是无符号数时,使用DIV指令,其商和余数也均为无符号数。IDIV指令执行的操作与DIV相同,但操作数必须是带符号数,商和余数也均为带符号数,而且余数的符号与被除数的符号相同。

  这两条除法指令的被除数必须存放在AX或DX,AX中,源操作数src作为除数,可用除立即数以外的任一种寻址方式来取得。

  除法指令对所有条件码均无定义,因此对除法指令产生的错误,如除数为0或商溢出等错误,程序员都不能用条件码进行判断,而是由系统直接转入0型中断来处理。所谓商溢出,是指被除数高一半的绝对值大于除数的绝对值时,商超出了16位的表示范围(字操作)或8位的表示范围(字节操作)。

  由于使用除法指令的需要,经常要将字节数据扩展为字数据,或者将字数据扩展为双字数据,所以我们先介绍下面的符号扩展指令,然后再对除法指令举例。

 3.3.2.5 符号扩展指令

 CBW 字节扩展为字(convert byte to word
 
 执行操作:
 (AH)= 00H 当(AL)的最高有效位为0时
 (AH)= FFH 当(AL)的最高有效位为1时

 CWD 字扩展为双字(convert word to double word
 
 执行操作:
 (DX)=0000H当(AX)的最高有效位为0时
 (AH)=FFFFH当(AX)的最高有效位为1时

 这是两条无操作数指令,进行符号扩展的操作数必须存放在AL寄存器或AX寄存器中。这两条符号扩展指令都不影响条件码。

 注意:
 除法指令要求字操作时,被除数必须为32位,除数是16位,商和余数是16位的;
 字节操作时,被除数必须为16位,除数是8位,得到的商和余数是8位的。

  例 假设(AX)= 0BA45H,下列指令分别执行后的结果是什么?
          CBW   ; 执行后,(AH)=00, (AL)=45H, 或 (AX)=0045H
          CWD   ; 执行后,(DX)=0FFFFH, (AX)=0BA45H

  例 编写程序,分别实现下列数据的无符号除法和带符号除法。
       DATA7  DW 9400H  ; numerator
       DATA8  DW 0060H  ; denominator
       QUOT   DW ?    ; quotient
       REMAIN DW ?    ; remainder
       ; unsigned divide
        MOV  AX,DATA7  ; AX holds numerator
        MOV  DX,0    ; (DX,AX)= 0000 9400H
        DIV  DATA8    ; unsigned divide
        MOV  QUOT,AX   ; quotient is in AX,(AX)=018AH
        MOV  REMAIN,DX ; remainder is in DX,(DX)=0040H
       ; signed divide
        MOV  AX,DATA7  ; (AX)=9400H
        CWD        ; (DX,AX)=0FFFF, 9400H
        IDIV DATA8   ; signed divide
        MOV  QUOT,AX  ; quotient is in AX,(AX)=0FEE0HH
        MOV  REMAIN,DX ; remainder is in DX,(DX)=0

 3.3.2.6 十进制调整指令

  80x86微型机提供了一组十进制调整指令,用来处理ASCII码和BCD码表示的数。
 
  BCD码
  BCD(Binary Coded Decimal)是用二进制编码表示的十进制数(见表3.3),十进制数采用0~9十个数字,是人们最常用的。在计算机中,同一个数可以用两种BCD格式来表示:①压缩的BCD码 ②非压缩的BCD码

  压缩的BCD码
  压缩的BCD码用4位二进制数表示一个十进制数位,整个十进制数用一串BCD码来表示。例如,十进制数59表示成压缩的BCD码为0101 1001,十进制数1946表示成压缩的BCD码为0001 1001 0100 0110。

  非压缩的BCD码
  非压缩的BCD码用8位二进制数表示一个十进制数位,其中低4位是BCD码,高4位是0。例如,十进制数78表示成压缩的BCD码为0000 0111 0000 1000。

  从键盘输入数据时,计算机接收的是ASCII码,要将ASCII码表示的数转换成BCD码是很简单的,只要把ASCII码的高4位清零即可。

  压缩的BCD码调整指令
  DAA和DAS指令完成加法和减法的调整功能。

  DAA 加法的十进制调整(decimal adjust for addition)
  执行操作:(AL)← 把AL中的和调整为压缩的BCD格式

  DAS 减法的十进制调整(decimal adjust for subtraction)
  执行操作:(AL)← 把AL中的差调整为压缩的BCD格式

  DAA和DAS指令的调整方法如下:
  执行加法指令(ADD、ADC)或减法指令(SUB、SBB)后,
  1.如果结果的低4位 (AL)0~3>9或AF=1,则(AL)←(AL)±06H,且AF置1;
  2.如果结果的高4位 (AL)4~7>9或CF=1,则(AL)←(AL)±60H,且CF置1。

  对上述方法,加法调整作+06H和+60H,减法调整作-06H和-60H。这两个调整的条件,如果满足其一,则±06H或±60H;如果同时满足,则±06H后,再±60H。

  非压缩的BCD码调整指令
  AAA
 加法的ASCII调整(ASCII adjust for add)
  执行操作:
  (AL)← 把AL中的和调整为非压缩的BCD格式
  (AH)←(AH)+ 调整产生的进位值

  AAS 减法的ASCII调整(ASCII adjust for sub)
  执行操作:
  (AL)← 把AL中的差调整为非压缩的BCD格式
  (AH)←(AH)- 调整产生的借位值

  加法和减法的操作数可以直接使用ASCII码,而不必把高位0011清为0000,AAA和AAS指令就是专门为ASCII码操作数或非压缩BCD码操作数的加减法而设计的。

  AAA和AAS的调整方法如下:
  执行加法指令(ADD、ADC)或减法指令(SUB、SBB)后,结果存放在AL寄存器中:
  (1)如果(AL)0~3= 0~9,且AF=0,则(AL)4~7= 0,AF的值送CF;
  (2)如果(AL)0~3=A~F,或AF=1,则(AL)←(AL)±06H,(AL)4~7= 0,(AH)←(AH)±1,AF的值送CF。
  AAA和AAS指令除影响AF和CF标志外,其余标志位均无定义。

  AAM 乘法的ASCII调整(ASCII adjust for mul
  执行操作:(AX)← 把AX中的积调整为非压缩的BCD格式

  AAD 除法的ASCII调整(ASCII adjust for div
  执行操作:(AX)← AX中的被除数(非压缩的BCD格式)转化为二进制数

  以上两条指令是专为非压缩的BCD码的乘除法而设计的,它们将乘法和除法的结果转换为非压缩的BCD码。
  
  注意:AAM和AAD都只对AX寄存器中的数进行调整,它们只影响SF、ZF和PF标志位,其它标志位无定义。

  AAM的调整方法为
  执行乘法指令(MUL)后,调整存放在AL寄存器中的乘积:
   (AH)←(AL)/ 0AH的商
   (AL)←(AL)/ 0AH的余数

  AAM实际上是将两个一位数的非压缩BCD码相乘后得到的乘积进行二化十的转换,十位数放在AH中,个位数放在AL中,那么AX中就是乘积的非压缩BCD码。

  注意:如果是两个ASCII码数相乘,要先将它们转换成非压缩BCD码。

  AAD的调整方法为
  执行除法指令之前,对AX中的非压缩BCD码(被除数)执行:
   (AL)←(AH)×10+(AL)
   (AH)← 0

  与其它调整指令不同的是,AAD用在DIV指令之前,即先将AX中的被除数调整成二进制数,并存放在AL中,再用DIV指令作二进制数的除法。AX中的被除数是二位非压缩BCD码,AH中的十位数乘10,再加上AL中的个位数,即转换为二进制数。

             表3.3 ASCII和BCD码

十进制数字 ASCII码 压缩BCD码 非压缩BCD码 0 0011 0000 0000 0000 0000 1 0011 0001 0001 0000 0001 2 0011 0010 0010 0000 0010 3 0011 0011 0011 0000 0011 4 0011 0100 0100 0000 0100 5 0011 0101 0101 0000 0101 6 0011 0110 0110 0000 0110 7 0011 0111 0111 0000 0111 8 0011 1000 1000 0000 1000 9 0011 1001 1001 0000 1001

 例 ASCII码转换为BCD码。
     
    ASC   DB '9562481273' ; ASCII string
        ORG   0010H
        UNPACK DB  10 DUP(?) ; store BCD number
    …    …
    MOV   CX,10   ; load the counter
    SUB   BX,BX   ; clear BX
AGAIN: MOV   AL,ASC[BX]; move to AL content of mem [BX+ASC]
    AND   AL,0FH   ; mask the upper nibble
    MOV   UNPACK[BX],AL  ; move to mem [BX+UNPACK] the AL
    NC    BX     ; make the pointer to point at next ASCII number
    LOOP   AGAIN   ; loop until finished

  上例中的AND指令完成逻辑与操作,AL寄存器的内容和0FH相与,结果使ASCII码的高4位清零,低4位保持不变,于是一个ASCII码数就转换成了BCD码。


  例 编写程序,实现BCD数据的加法和减法。

     ① BCD3←BCD1+BCD2  ; BCD3=2784+1839=4623
     ② BCD3←BCD1-BCD2  ; BCD3=2784-1839=0945

    编写程序如下:
     DATA SEGEMENT
     BCD1 DB 84H,27H ; BCD format of 2784
     BCD2 DB 39H,18H ; BCD format of 1839
     BCD3 DB 2 DUP(?)
     DATA ENDS

    ① MOV  AL,BCD1   ; AL←84H
      ADD  AL,BCD2   ; AL←84H+39H=0BDH (B>9,D>9)
      DAA        ; AL←0BDH+06+60H=23H, AF=1,CF=1
      MOV  BCD3,AL   ; BCD3←23H
      MOV  AL,BCD1+1  ; AL←27H
      ADC  AL,BCD2+1  ; AL←27H+18H+1=40H, AF=1,CF=0
      DAA        ; AL←40H+06=46H, because AF=1
      MOV  BCD3+1,AL  ; BCD3+1←46H

    ② MOV  AL,BCD1   ; AL←84H
      SUB  AL,BCD2   ; AL←84H-39H=4BH (4≯9,B>9)
      DAS        ; AL←4BH-06=45H, AF=1, CF=0
      MOV  BCD3,AL   ; BCD3←45H
      MOV  AL,BCD1+1  ; AL←27H
      SBB  AL,BCD2+1  ; AL←27H-18H=0FH
      DAS        ; AL←0FH-06=09H, because F>9
      MOV  BCD3+1,AL  ; BCD3+1←09H

   使用DAA和DAS指令,注意:
   · 被调整的数必须在AL寄存器中;
   · 影响除OF外的其它条件码标志;
   · DAA必须紧接在加指令之后,DAS必须紧接在减指令之后。

  例 两个ASCII码数5和2相加,要求结果也为ASCII码。
     
     MOV  AL,'5'    ; AL←35H
     ADD  AL,'2'    ; AL←35H+32H=67H, AF=0
     AAA         ; changes 67H to 07H,
     OR   AL,30     ; OR AL with 30H to get ASCII

 例 编写15和7的非压缩BCD码的减法程序,要求结果也为非压缩BCD码。

     MOV  AX,0105H   ; unpacked BCD for 15
     MOV  CL,07
     SUB  AL,CL     ; (AL)←05-07 =-2 (FEH)
     AAS         ; adjusted: 0FE-06=0F8→08→(AL),
               ; 01-1=00→(AH), leaving (AX)=0008

 例 两个ASCII码数7和8相乘,要求结果也为ASCII码。

     MOV  AL,'7'    ; (AL)=37H
     AND  AL,0FH    ; (AL)=07 unpacked BCD
     MOV  DL,'6'    ; (DL)=36H
     AND  DL,0FH    ; (DL)=06 unpacked BCD
     MUL  DL      ; (AX)=07×06=002AH=42
     AAM         ; (AX)=0402 (7×6=42 unpacked BCD)
     OR   AX,3030H   ; (AX)=3432 result in ASCII

 例 编写ASCII码数的除法程序。

     MOV  AX,3539H   ; (AX)=3539, ASCII for 59
     AND  AX,0F0FH   ; (AH)=05,(AL)=09,unpacked BCD data
     AAD         ; (AX)=003BH=59
     MOV  BH,08H    ; divide by 08
     DIV  BH      ; 3BH/8 gives (AL)=07,(AH)=03
     OR   AX,3030H   ; (AL)=37H (quotient), (AH)=33H (remainder)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值