计算机编码中,我们都是先了解了二进制,其中分有符号数,无符号数,然后会接触到BCD码,那么BCD码是怎么产生的?为什么又要用四位二进制来表示呢?
一、BCD码
1.由来
计算机使用二进制数来处理信息,但是如果二进制的形式输入和输出数据,就十分不方便了。一般来说,输入输出时采用十进制数。
举例: 明明二进制 0110 (B)代表数字 6,但是人们更习惯,也更喜欢的数 阿拉伯数字 6 ,也可以是 中文 六。
那么,这里就存在一个问题,我们使用计算器,是输入的为十进制数 25,但是计算机使用二进制数来处理信息,那么就得将 25 (D)转化成 0001 1001 (B),同样计算 25 + 25时,计算机也是处理二进制的25相加,而运算结果 0011 0010(B)还是的需要转化为 十进制 50,展示给人看。而人是直接使用十进制运算。
如图,看出,计算机处理人类的计算,需要多两步的转换。那么,计算次数越多,这损失的效率越大。
那么怎么解决?
前人想出了,一种比较适合十进制系统的二进制编码的特殊形式,即将1位十进制的0~9这十个数字分别用4位二进制的组合来表示,在此基础上可按位对任意十进制数进行编码。
2.8421BCD码
BCD英文是 Binary-Coded Decimal ,二进制编码的十进制。直接明了。
BCD码有很多,例如格雷码,余三码,但用的最多的8421BCD码。
8421BCD码,因为代码中从左至右看每一位“1”分别代表数字“8”“4”“2”“1”,故得名8421码。其中每一位“1”代表的十进制数称为这一位的权。因为每位的权都是固定不变的,所以8421码是恒权码。
压缩BCD码与非压缩BCD码的区别
- 压缩BCD码的每一位用4位二进制表示,一个字节表示两位十进制数。例如10010110B表示十进制数96D
- 非压缩BCD码用1个字节表示一位十进制数,高四位总是0000,低4位的0000 ~ 1001表示0~9.例如00001000B表示十进制数8.
表示: 246 (D)
0010 0100 0110 (8421BCD)
3.修正
需要说明的是,虽然BCD码可以简化人机联系,但它比纯二进制编码效率低,对同一个给定的十进制数,用BCD码表示时需要的位数比用纯二进制码多,而且用BCD码进行运算所花的时间也要更多,计算过程更复杂,因为BCD码是将每个十进制数用一组4 位二进制数来表示,若将这种BCD码送计算机进行运算,由于计算机总是将数当作二进制数来运算,所以结果可能出错,因此需要对计算结果进行必要的修正,才能使结果为正确的BCD码形式。
我们都知道,38 + 49 = 87 ,其BCD码是 1000 0111
结果是错误的。其原因是,十进制数相加应该是“逢十进”,而计算机按二进制数运算,每4位为一组,低4位向高4位进位与十六进制数低位向高位进位的情况相当,是“逢十六进一”,所以当相加结果超过9时将比正确结果少6,因此结果出错。解决办法是对二进制加法运算结果采用“加6修正”,从而将二进制加法运算的结果修正为BCD码加法运算结果。
BCD数相加时,对二进制加法运算结果修正的规则如下:
- 如果两个对应位BCD数相加的结果向高位无进位,且结果小于或等于9,则该位不需要修正;若得到的结果大于9而小于16,则该位需要加6修正。
- 如果两个对应位BCD数相加的结果向高位有进位(结果大于或等于16),则该位需要进行加6修正。
例如:
因此,两个BCD数进行运算时,首先按二进制数进行运算,然后必须用相应的调整指令进行调整,从而得到正确的BCD码结果。
同样使用BCD码的优点也显示出来了,基于同一个加法器,只需要增加一个修正电路,就能简化二进制和十进制的转换。利于人机交互。
二、底层验证修正计算
计算机到底有没有对于BCD码修正呢?我们使用汇编语言来一探究竟。
1.无修正计算
我们再以 7+8为例。
jmp start
db 8
db 7
start: mov al, [102h]//将地址为[102h]存储的数(8)复制到AX寄存器的低八位
mov bl, [103h]//将地址为[103h]存储的数(7)复制到BX寄存器的低八位
add al, bl //两数相加,结果保存在al上
ret
运行start前:
mov al, [102h] // 将地址为[102h]存储的数(8)复制到AX寄存器的低八位
mov bl, [103h] // 将地址为[103h]存储的数(7)复制到BX寄存器的低八位
add al, bl //两数相加,结果保存在al上
同时:
ret //返回
计算机对于7 和 8 就是看成无符号的二进制数。进行相加,结果也就是 0000 1111
2.有修正计算
DAA(daa)是关于BCD码的调整指令。
在add指令后增加daa
原因: 加运算,通常采用两种方法 : 一种是在指令系统中设置一套专用于BCD码运算的指令: 另一种是利用二进制数的运算指令算出结果,然后再用专门的指令对结果进行修正(调整),使之转变为正确的BCD码表示的结果。8086/8088 指令系统所采用的是后一种方法。
未修正时:
开始修正:
确实存在修正操作。而且此时AX寄存器的低八位 存储的是 0001 0101 。转成8421BCD码来读就是15。
7 + 8等于15。
总结:
创造一个东西,从来不是完美的。就像没有完美的代码。
但不断改善与优化我们创造的,就是一种完美。
笔者水平有限,目前只能描述以上问题,如果有其他情况,可以留言,有错误,请指教,有继续优化的,请分享,谢谢!
本篇文章是否有所收获?阅读是否舒服?又什么改进建议?希望可以给我留言或私信,您的的分享,就是我的进步。谢谢。
2020.9.16 网安院2楼