BCD和非BCD

BCD和非BCD的作用


大家都知道在计算机里面都是使用二进制,其实,8086/8088 CPU 也可以使用十进制进行计算的。

在计算机中的十进制数称为 BCD 码,它是使用四位二进制数,表示一位十进制数字。

常见的 BCD 码是 8421 码。即:0000 ~ 1001 分别代表 0 ~ 9。

一个字节有 8 位数,可以代表两位十进制数,即:0000 0000 ~ 1001 1001,分别代表 0 ~ 99。

二进制的写法,太长了,写成 16 进制好看些,即:00H ~ 99H,代表十进制的 0 ~ 99。

用一个字节代表两位十进制数,这称为压缩的 BCD 码。
如果只是使用低四位,一个字节代表就只能代表一位十进制数,这称为非压缩的 BCD 码

用 BCD 码代表十进制进行数值计算,我们的希望是“逢十进一”。
但是,CPU 是按照二进制计算的,它只会“逢二进一”。
那么,低四位向高低位进位的时候,仅仅是超过 15 的时候才进位,即逢 16 进一

  1. 如果用 BCD 码相加,希望低四位(或高四位)能够“逢十进一”,那就在它们超过了 9 、应该进位而没有进位的时候,给它再加上 6,它就可以进位了。
  2. 另外,如果已经发生了进位,这个进位 1,就代表进走了 16,比十进制多进走了 6,此时,也应该再加上 6。

BCD码运算结果为何要进行调整?
• 例1:计算38+29=?
采用BCD码进行运算: 00111000+00101001=01100001(61)
但是正确的结果是 67 结果相差6
• 例2:计算25+16=?
采用BCD码计算: 00110101+00010110=00111011
结果的低四位是非法的8421码
• 出错的原因
第一个例子中, D3向D4产生了一个进位,即AF=1(半进位)这个半进位相当于16,而按照十进制正常的进位是10,所以相比于十进制的进位多进了6,故结果比正常的少了6.
调整:当有半进位时,在低位的BCD码上再加6(0110)进行调整。
• 第二个例子:在个位数的运算中不足以引进半进位(5+6=11<16),而按照十进制的运算规
则它应该向高位进位,使得高位的BCD码没有得到进位而出错。
调整:相加结果的低位BCD码大于9时,加上0110(6),迫使其向高位产生进位。
即: 00111011+00000110=01000001=41

这两个步骤,称为十进制调整。经过十进制调整,运算结果就符合十进制的运算规则了。

在 8086/8088 CPU 指令系统中,具有这种调整指令:DAAAAA

  • 在压缩的 BCD 码相加后,使用DAA指令,它就会把结果调整为符合十进制运算的 BCD 码。 如果是非压缩的 BCD码相加,则应该使用AAA 指令。

其它几种 BCD 码的运算,应该使用的调整指令如下:

  • 压缩的 BCD 码相减后,应使用 DAS 指令;

  • 非压缩的 BCD 码相减后,应该使用 AAS 指令;

  • 非压缩的 BCD 码相乘后,应该使用 AAM 指令;

  • 非压缩的 BCD 码相除后,应该使用 AAD 指令。

注意,没有压缩的 BCD 码相乘、除后的调整指令。

这些 BCD 码的十进制调整指令,都是对 AL 中的运算进行调整。因此,各种 BCD 码的运算,都应放在 AL 中进行。

十进制调整指令的应用例题。


一、非压缩的 BCD 码的加法

;12345+67890=80235 计算并全部显示出来

DATAS SEGMENT
   X  DB  1, 2, 3, 4, 5  ;存放5位十进制数
   Y  DB  6, 7, 8, 9, 0  ;都是非压缩的BCD码
   Z  DB  6  DUP(?)      ;6位数的和
DATAS ENDS

CODES SEGMENT
    ASSUME CS:CODES, DS:DATAS
START:
    MOV  AX, DATAS
    MOV  DS, AX
    MOV  SI, 0
    MOV  CX, 5           ;计划循环5次
    K1: MOV  DL, X[SI]       ;取出一位X
    ADD  DL, 30H         ;变成ASCII码
    MOV  AH, 2           ;显示在屏幕
    INT  21H
    INC  SI              ;指向下一位
    LOOP K1
    MOV  DL, '+'         ;显示加号
    MOV  AH, 2
    INT  21H
    MOV  SI, 0
    MOV  CX, 5
    K2: MOV  DL, Y[SI]
    ADD  DL, 30H
    MOV  AH, 2           ;显示5位数Y
    INT  21H
    INC  SI
    LOOP K2
    MOV  DL, '='         ;显示等号
    MOV  AH, 2
    INT  21H
;5位非压缩的BCD码相加.
    CLC            ;clean carryflag   
    MOV  SI, 4
    MOV  CX, 5           ;循环加5次
    K3: 
    MOV  AL, X[SI]       ;X、Y都是非压缩的BCD码
    ADC  AL, Y[SI]       ;在AL中相加
    AAA                  ;非压缩的BCD码调整
    MOV  Z[SI + 1], AL   ;保存和数
    DEC  SI
    LOOP K3 
;---------------下面第6位BCD码.
    MOV  AL, 0
    ADC  AL, 0
    MOV  Z, AL
;---------------下面是6位和的BCD码显示.
    MOV  SI, 0
    MOV  CX, 6           ;显示6位
K4: MOV  DL, Z[SI]
    ADD  DL, 30H
    MOV  AH, 2
    INT  21H
    INC  SI
    LOOP K4
;---------------下面就结束程序.
    MOV  AH, 4CH
    INT  21H
    CODES ENDS
    END START

从这个程序来看,进行多位数的加减法计算,用 BCD 码是十分方便的,位数的多少,几乎就没有障碍 特别是显示,要比使用二进制来计算后,再用十进制数字的显示,要方便的多

二、压缩的 BCD 码相乘

  • 压缩的 BCD 码相乘,8086/8088 指令系统中并没有相应的十进制调整指令,因此,就不能使用乘法指令了。那么,这个乘法,就只能用“累加”的方法来做
    即:用乘数当做循环次数,循环的把被乘数加起来。每一次循环,加一次被乘数,乘数减一次一,直到减到0。

  • 这里的加、减,都是 BCD 码运算,加减之后,都要用十进制调整。

;压缩BCD码相乘程序

DATA  SEGMENT
 N1  DB  28H     ;28  ,写两个压缩的BCD码
 N2  DB  04H     ; 4  ,当做乘数
 Product  DW  ?  ;乘积,结果应为0112H,即28*4=112
DATA  ENDS

CODE  SEGMENT
   ASSUME CS:CODE, DS:DATA
START:
   MOV  AX, DATA
   MOV  DS, AX
;-----------------------------------------
   MOV  AX, 0   ;积为0
   MOV  CL, N2  ;相加的次数
AGAIN:
   ADD  AL, N1  ;N1加入到积中
   DAA          ;压缩BCD码的加法十进制调整
   XCHG AH, AL  ;交换高8位

   ADC  AL, 0   ;高8位加上进位
   DAA          ;调整
   XCHG AH, AL  ;交换回来
   
   XCHG AL, CL  ;相加的次数
   SUB  AL, 01  ;减一
   DAS          ;压缩BCD码的减法十进制调整
   XCHG AL, CL  ;送回
   JNZ  AGAIN   ;非0转移,继续累加
   
   MOV  Product, AX ;保存乘积

;-----------------------------------------
   MOV  AH, 4CH
   INT  21H
CODE ENDS
   END  START

DAA、DAS,这两条指令,只能用在AL的加减运算的后面。
因此,其它寄存器的运算,都要弄到AL中来进行,算完了,再弄回去。所以,要来回的换。

三、16 进制数变换成 ASCII 码

16 进制数 0 ~ 9、A ~ F 变换成 ASCII 码 30H ~ 39H、41H ~ 46H,需要分别对数字加上 30H 或 37H。
这种变换一般都是使用分支程序、查表程序的方法。

还有一种使用十进制调整的方法,程序非常简单,但是技巧性很强,一般人是难以理解的。

程序片断如下:

MOV  AL,  X    ;取来数字0~9、A~F
ADD  AL,  90H
DAA
ADC  AL,  40H
DAA
MOV  Y,  AL    ;保存ASCII码
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值