2.1 计算机中的数、编码和运算
2.1.1 计算机中常用的数制及相互转换
计算机要能计算,首先必须解决数和其他信息的表达问题。
1.计算机中常用的数制
数制是人们利用符号来记数的科学方法。数制可以有很多种,但在计算机的设计与使用上,常用的有十进制、二进制、八进制和十六进制。
存在决定意识。拥有十个手指这个客观存在,使得人类在远古时代就想到了采用十进制数来记数。计算机要能计算,首先必须解决记数问题。如果用物理器件的一个状态来表示和存储一个数的话,显然基数越多系统越复杂,而基数最少的二进制只有“0”和“1”两个基数,因而可以方便地用二值电路来表达。用电路来组成计算机,有运算迅速、电路简便、成本低廉等优点,这也正是在计算机中为什么要使用二进制的根本原因。
虽然二进制数便于机器表达,但其过于冗长的缺点却给人们的书写、阅读及记忆带来了不便,于是十六进制数便应运而生。八进制数的引入也是基于这个原理。
2.不同数制间的转换
由于人们习惯用十进制记数,在研究问题或讨论解题的过程时,总是用十进制数来考虑和书写。考虑成熟后,要把问题变成计算机能够“看得懂”的形式时,就得把问题中的所有十进制数转换成二进制代码。这就需要用到“十进制数转换成二进制数的方法”。在计算机运算完毕得到二进制数的结果时,又需要用到“二进制数转换为十进制数的方法”,才能把运算结果用十进制形式显示出来。3种常用数制间的转换方法可总结为如图2-1所示。
图2-1 3种常用数制间的转换方法
2.1.2 微型计算机中常用的编码
由于微型机不但要处理数值计算问题,还要处理大量非数值计算问题,因此,不论是十进制数还是英文字母、汉字及某些专用符号等,都必须变换成二进制代码。这样,它们才能被计算机识别、接收、存储、传送和处理。
微型计算机中常用的编码有十进制数的编码和非数值数据的编码两大类。常用的十进制数的编码有BCD码、余3码和格雷码;常用的非数值数据的编码有ASCII码和汉字编码。下面重点介绍BCD码和ASCII码。
1.BCD码(十进制数的二进制编码)
在微型机中,十进制数除了转换成二进制数进行处理外,还可用二进制数对其进行编码(通常用4 位二进制数表示一位十进制数),使它既具有二进制数的形式又具有十进制数的特点。二-十进制码又称为BCD码(Binary Coded Decimal)。由于4位二进制数能编出16个码,其中有6个是多余的,应该放弃不用。而这种多余性便产生了多种不同的BCD码,其中最常用的是842l码。8421 码与十进制数的对照关系见表2-1。从表中可以看出,在8421BCD码中决不允许出现1010~1111这6个代码(它们被称为禁用码)。10以上的十进制数至少需要两位BCD码(即8位二进制数)来表示,而且不应该出现禁用码,否则就不是BCD码。因此BCD数是由BCD码构成的,是以二进制形式出现的,但它不是真正的二进制数。例如,十进制数25的BCD码形式为00100101B(即25H),而它等值的二进制数为00011001B(即19H)。
表2-1 8421BCD码编码表
2.ASCII码
由于微型机需要进行非数值处理(如指令、数据的输入、文字的输入及处理等),必须对字母、文字及某些专用符号进行编码。微型机系统的字符编码多采用美国信息交换标准代码,即ASCII码(American Standard Code for Information Interchange)。
ASCII码是7位代码,共可为128个字符编码,如附录A所示。包括96个图形字符和32个控制字符。在8位微型计算机中,信息通常是按字节存储和传送的,一个字节有8位,而ASCII码共有7位,作为一个字节还多出一位,多出的位为最高位,常用做奇偶校验,故称为奇偶校验位。奇偶校验位在信息传送时用途很大,可用来检验信息在传输过程中是否出错,常用于微型计算机通信中。
请读者注意,0~9的数字字符其相应的ASCII码为30H~39H,大写英文字母A~F其相应的ASCII码为41H~46H,这些符号的ASCII码在数码转换中经常要用到。
2.1.3 微型计算机的运算基础
1.带符号数的表示法
计算机中处理的数值数据可分为无符号数和有符号数两类。
(1)机器数与真值
数学中的正负用符号“+”和“-”表示。而在计算机中,数字存放在由存储元件构成的寄存器或存储器中,二进制的数字符号1和0是用电路的两种不同稳定状态(如高、低电位)来表示的。数的符号“+”或“-”也要用这两种状态来区别。例如,正数的符号用“0”表示,负数的符号用“1”表示。用来表示数的符号的数位被称为“符号位”(通常为最高数位),这样就使数的符号也“数码化”了,即从表达形式上看符号位与数值位毫无区别。这种符号数码化的数被称为机器数,而把原来的带正负号的数称为相应机器数的真值。
机器数是计算机中数的基本形式,为了运算方便,机器数通常有原码、反码和补码3种形式。关于原码和反码的定义及求取方法在先修课程中已有详尽介绍,在此不再赘述。下面重点介绍补码的定义及运算。
(2)补码的概念及定义
首先以日常生活中经常遇到的钟表为例来说明补码的概念。假定现在是北京标准时间2时整,而一只表却指向3时整。为了校正此表,可以采用倒拔和顺拔两种方法。倒拔就是反时针减少1小时(把倒拔视为减法,相当于3-1 = 2),时针指向2。还可将时针顺拔11时,时钟同样也指向2。把顺拔视为加法,相当于3 + 11 = 12(自动丢失)+ 2 = 2。这个自动丢失的数(12)就称为模(mod),即一个系统的量程或此系统所能表示的最大数。上述的加法就称为“按模12的加法”,用数学式可表示为
3 + 11 = 2(mod 12)
因时针转一圈会自动丢失一个数12,故3-2与3 + 11是等价的。称11和-1对模12互补,11是-1对模12的补码。引进补码的概念后,就可将原来的减法3-1 = 2转化为加法3 + 11 = 2(mod 12),这正是引入补码的主要意义。
可以分别从模和反码这两个概念引出补码的具体定义,下面分别阐述之。
① 以模的概念定义补码
通过上面的例子不难理解计算机中负数的补码表示法。设寄存器(或存储单元)的位数为n位,则它能表示的无符号数的最大值为2n-1,逢2n进一(即2n自动丢失)。换言之,在字长为n的计算机中,数2n和0的表示形式一样。若机器中的数以补码表示,则数的补码以2n为模。即
由式(2-1)可知:
若X为正数,则[X]补 = X,即正数的补码是它本身。
若X为负数,则[X]补 = 2n + X = 2n-|X|,即负数的补码等于2n(模)加上其真值,或者等于2n(模)减去其真值的绝对值。
② 利用反码定义补码
(3)补码的求取方法
根据前述介绍可知,正数的补码等于原码。下面介绍负数求补码的3种方法。
① 利用模求补码
按式(2-1)有:[X]补 = 2n + X = 2n-|X|
即负数的补码等于2n(模)加上其真值,或者等于2n(模)减去其真值的绝对值。
【例2-1】 已知X =-1001011B,试求[X]补。
解:根据式(2-1)可知
[X]补 = 2n + X = 28-1001011B = 10110101B
② 利用十六进制数形式求取补码的便捷方法
二进制数常常以十六进制数的形式来表示,对于十六进制数的补码依然可以用式(2-1)来定义和计算。
以8位微型机中常用的单字节数为例,此时,n = 8,模2n=28=100H,式(2-1)可改造为
如果X≥0,则[X]补 = X
如果X < 0,则[X]补 = 100H -|X|
这种求补码的方法在分析数据时便于手工计算。例如,X =-2,则 X 的补码用单字节十六进制数表达,就是[X]补 = 100H-02H = FEH。
③ 根据反码求补码
首先求真值对应的原码,再求相应的反码,最后根据式(2-2)得到原数对应的二进制形式的补码。这种利用取反加1求负数补码的方法,便于在逻辑电路中利用非门电路和加法计数器的功能实现。
(4)由补码求取真值的方法
需要特别指出的是,在计算机中凡是带符号的数一律用补码表示,且符号位参加运算,其运算结果也用补码表示。若结果的符号位为“0”,则表示结果为正数,此时可以认为它是以原码形式表示的(正数的补码即为原码);若结果的符号位为“l”,则表示结果为负数,它也是以补码形式表示的。若要用原码来表示该结果,还需要对结果求补,即
求得X的原码后只需简单地对符号位做出处理就可得到对应的真值。
【例2-2】 已知 [X]补 = 10011001B,求X。
解:根据式(2-4)可得[X]原 = [[X]补]补 = 11100111B,所以X =-1100111B。
2.补码运算规则
既然在计算机中凡是带符号的数一律都是用补码表示的,因此,对这些带符号数直接进行运算时实际上是用补码进行的运算。那么,这些补码运算的结果与真值间是什么关系呢?应该如何转换呢?这正是补码运算规则要阐述的问题。
(1)补码的加法
设X和Y是两个带符号的二进制数,则根据式(2-1)有
由此得
[X + Y]补 = 2n + (X + Y) = (2n + X) + (2n + Y) = [X]补 + [Y]补
即两个数和的补码等于两个数补码的和。
得到两数和的补码后,再对其求补,即得到两数之和的原码。
(2)补码的减法
两个带符号数相减,有如下基本公式
由此得
[X-Y]补 = [X + (-Y)]补 = [X]补 + [-Y]补
X-Y=X+ (-Y)
即两数差的补码等于被减数的补码与减数的相反数的补码之和。这说明了在补码运算中,减法运算可以转化为加法来实现。
这里的关键在于求[-Y]补。如果已知[Y]补 = Yn-1Yn-2…Y0,那么对于[Y]补的每一位(包括符号位)都按位求反,然后再加1,结果即为[-Y]补。
一般称[-Y]补为对[Y]补“变补”,即[[Y]补]变补 = [-Y]补,它有别于[[Y]补]补 = [Y]原。
已知[Y]原求[Y]补的过程叫求补;已知[Y]补求[-Y]补的过程叫变补。变补并不是一种编码,而只是一个操作过程,这一点务必注意。
【例2-3】 用补码运算求64-65。
解:① [64]补= 01000000B,[65]补= 01000001B,[-65]补=10111111B
② 做加法:[64]补+[-65]补=01000000B+10111111B=11111111B
③ 求真值:由于是负数,要对结果除符号位外取反加1,结果即为:-(00000001B) =-1。
3.数值数据运算的溢出问题
(1)溢出的概念
在微型计算机中,带符号数都是以补码形式存放的。根据指令,这些数可以进行加法运算,也可以进行减法运算。但在实际机器中只有加法器,减法运算也是通过加法运算来完成的,且运算结果也是用补码表示的。由于计算机的字长有一定范围,所以一个带符号数也是有一定范围的。
表2-2列出了8位二进制数的概况。由表可以看出,8位二进制数的原码和反码形式所表示的数的范围都是-127~+127,而补码表示的数的范围是-128~+127。
表2-2 8位二进制数的表示形式
当两个带符号位的二进制数进行补码运算时,若运算结果的绝对值超过了这个范围,数值部分便会占据符号位的位置,从而造成错误的运算结果,这就是溢出。
【例2-4】 用补码运算求64 + 65。
解:① [64]补 = 01000000B,[65]补 = 01000001B
② 做加法:[64]补 + [65]补 = 01000000B + 01000001B = 10000001B
结果为一个负数,这显然是错误的,原因就在于,在字长为8位的情况下,64 + 65的结果是129,超过了单字节补码所能表达的范围,因此,出现了溢出错误。
(2)采用补码进行加减运算时要注意的几个问题
① 补码运算时,其符号位要与数值部分一样参加运算,但结果不能超出其所能表示的数的范围,否则会出现溢出错误。无符号数的加减运算结果超出数的范围的情况称为产生进位或借位,计算机中有专门的标志用来记录运算时产生进位、借位或溢出的情况,只要适当处理这些标志,如将进位加到高位上或者将借位从更高位上减去就不会出错,所以在多字节数的加减运算时,必须考虑进位和借位的处理。
② 采用了补码以后,符号位参与运算后如有进位出现,只要是没有产生溢出错误,则可把这个进位舍去,不影响运算结果,运算后的符号就是结果的符号。
4. 二进制数的运算
微型计算机中的运算分为两类:一类是算术运算,包括加、减、乘、除;另一类是逻辑运算,包括逻辑乘、逻辑加、逻辑非和逻辑异或等。具体运算规则在先修课程中已有详尽介绍,在此不再赘述。
算术运算有加、减、乘、除共4种,根据前面的分析,引入补码后,减法可以转化为加法来实现,乘法可以利用加法和移位通过编程来实现,而除法也可以利用减法和移位通过程序来实现。更复杂的运算如指数、对数及其他函数的运算都可运用数值计算的方法最终转化为四则运算式来实现。由此可以看出,加法是计算机最基本的运算功能,加法器是计算机运算器的核心部件。