1.4 常见问题解答

1. 同一个功能可以由软件完成也可以由硬件完成吗?

答:软件和硬件是两种完全不同的形态:硬件是实体,是物质基础;软件是一种信息,看不见、摸不到。但是它们都可以用来实现逻辑功能,所以在逻辑功能上,软件和硬件是等价的。因此,在计算机系统中,许多功能既可以直接由硬件实现,也可以在硬件的配合下由软件来实现。例如,乘法运算既可以用专门的乘法器硬件实现,即机器提供专门的一条乘法指令;也可以用乘法子程序来实现,即不提供乘法指令,而由加法指令和移位指令等组成的指令序列来完成乘法运算。

2. 解释程序和编译程序有什么差别?

答:编译程序和解释程序是两种不同的翻译程序。不同在于编译程序将高级语言源程序全部翻译成目标程序,每次执行程序时,只需执行目标程序,因此,只要源程序不变,就无须重新翻译;解释程序是将源程序的一条语句翻译成对应的机器目标代码并立即执行,然后翻译下一条语句并执行,直至所有源程序中的语句全部被翻译并执行完。所以解释程序的执行过程是翻译一句,执行一句。解释的结果是源程序执行的结果,而不会生成目标程序。

3. 要计算机做的任何工作都要先编写成程序才能完成吗?

答:对于冯·诺依曼结构计算机来说,是这样的。要计算机完成的任何事情,都必须先编制程序,程序是由指令构成的。不管是用哪种语言编写的程序,最终都要翻译成机器语言程序才能让机器理解,机器语言程序是由一条条指令组成的程序。CPU的主要功能就是周而复始地执行指令,因此,要计算机完成的所有功能都是通过执行一条条指令来实现的,也就是由一个程序来完成的。有时我们说某个特定的功能是由硬件实现的,并不是说不需要编写程序,如乘法功能可由乘法器这个硬件实现,但要启动这个硬件(乘法器),必须先执行程序中的乘法指令。

4. 指令和数据在形式上没有差别,且都存于存储器中,计算机如何区分它们呢?

答:指令和数据在计算机内部都是用二进制表示的,因而都是01序列,在形式上没有差别。在指令和数据被取到CPU之前,它们都存放在存储器中,CPU必须能够区分读出的是指令还是数据。如果是指令,CPU会把指令的操作码送到指令译码器进行译码,而把指令的地址码送到相应的地方进行处理;如果是数据,则送到寄存器或运算器。那么,CPU如何识别读出的是指令还是数据呢?实际上,CPU并不是把信息从主存读出后,靠某种判断方法来识别信息是数据还是指令的,而是在读出之前就知道将要读的信息是数据还是指令了。执行指令的过程分为取指令、指令译码、取操作数、运算、送结果等。因此,在取指令阶段,总是根据程序计数器(PC)的值去读存储器,这时取出的是指令,而取操作数阶段取出的是数据。

5. 真值和机器数的关系是什么?

答:在计算机内部用二进制编码表示的数称为机器数,而机器数真正的值(即原来带有正负号的数)称为机器数的真值,因此它们之间的关系就是同一个数据在计算机内外的两种不同表示形式。

6. 什么是编码?

答:编码是指用少量简单的基本符号,对大量复杂多样的信息进行一定规律的组合。基本符号的种类和组合规则是信息编码的两大要素。例如,用10个阿拉伯数字表示数值,电报码中用4位十进制数字表示汉字等,都是编码的典型例子。计算机内部处理的所有信息都是数字化编码的信息。

7. 什么是数字化编码?

答:数字化编码就是对感觉媒体信息(如数值、文字、图像、声音、视频等信息)进行定时采样,将现实世界中的连续信息转换为计算机中离散的样本信息,然后对这些离散的样本信息进行二进制编码。

8. 计算机内都用二进制表示信息,为什么还要引入八进制和十六进制?

答:计算机内部在进行信息的存储、传送和运算时,都以二进制形式表示。但在屏幕上或书本上书写信息时,由于二进制信息位数多,阅读、记忆不方便,而十六进制、八进制和二进制的对应关系简单,又便于阅读、记忆和书写,所以引入十六进制或八进制,这使得人们在开发、调试程序和阅读机器内部代码时,能方便地用八进制或十六进制来等价表示二进制信息。

9. 如何表示一个数值数据?计算机中的数值数据都是二进制数吗?

答:在计算机内部,数值数据的表示方法有以下两大类。①直接用二进制数表示,分为无符号数和有符号数,有符号数又分为定点整数和浮点数。无符号数用来表示无符号整数(如地址等信息),定点整数用来表示带符号整数,浮点数用来表示实数。②采用二进制编码的十进制数(即BCD码)表示整数,BCD码的编码方案很多,但一般都采用8421码(也称为NBCD码)来表示。

由此可见,计算机中的数值数据虽然都用二进制来编码表示,但不全是二进制数,也有用十进制数表示的。因而有些处理器的指令类型中,就有对应的二进制加法指令和十进制加法指令。

10. 为什么要引入无符号整数表示?

答:因为有些情况下只要对正整数进行运算,且结果不出现负值,此时,可用无符号整数表示变量。

11. 在高级语言程序中定义的unsigned型数据是怎么表示的?

答:unsigned型数据就是无符号整数,直接用二进制对数值进行编码得到的就是无符号整数。

12. 为什么无符号整数运算时结果可能会发生溢出?什么叫无符号整数的溢出?

答:计算机的机器字长是有限的,因而机器数位数有限,使得可表示数的大小有限。对于n位二进制数,只能表示2n个不同的数,当运算结果超过n位数时就可能发生溢出。计算机是一种模运算系统,运算过程中仅保留低n位,舍弃高位。这样会产生以下两种结果。

(1)剩下的低n位数不能正确表示运算结果。这种情况下,意味着运算的结果超出了计算机能表达的范围,有效数字进到了第n+1位,此时便发生了溢出。例如,对于4位无符号整数相加运算,当计算14+3时就会发生溢出,即1110+0011=1 0001,结果中第一位1被舍弃后,结果就不对了。

(2)剩下的低n位数能正确表示计算结果,也即高位的舍弃并不影响运算结果。例如,对于4位无符号整数相减运算,当计算14-3时,用14加-3的补码来实现,即1110 + 1101 = 1 1011,结果中第一位1舍弃后的结果是十进制的11,结果正确。

“对一个多于n位的数舍弃高位而保留低n位数”这样一种处理,实际上等价于“将这个多于n位的数除以2n,结果保留余数”的操作。这种操作就是模运算。在模运算系统中,运算的结果最终都是丢弃高位而保留低位。

13. 为什么现代计算机都用补码来表示整数?

答:和原码、反码相比,用补码表示定点整数时,有以下4个好处。①符号位可以和数值位一起参加运算;②补码可以实现模运算,即可用加法方便地实现减法运算;③零的表示唯一;④可以多表示一个最小负数。

14. n位二进制补码整数的模是多少?数的表示范围是什么?

答:n位二进制补码整数的模是2n,表示其运算结果只保留低n位,多于n位的高位部分取模后被丢弃,其数值范围为-2(n-1)~+ 2(n-1)–1。

15. 在C语言程序中,关系表达式“–2147483648==2147483648U”的结果为什么为“真”?

答:关系表达式“-2147483648==2147483648U”的左边是负数,右边是正数,因此,左右两数看似不等,结果似乎应该为“假”。但是,根据C语言标准给出的数据类型提升规则,如果在一个表达式中同时有unsigned型和int型数据,必须将int型数据转换为unsigned类型。在上面的关系表达式运算中,对于等号左边的数-2147483648,编译器会先把2147483648转换为机器数1000 0000 0000 0000 0000 0000 0000 0000,然后将负号“-”转换为一条取负指令,得到对应的机器数还是1000 0000 0000 0000 0000 0000 0000 0000,被解释成无符号整数,其真值为231,和右边的无符号整数2147483648U的值完全相同,因而结果为真。

16. 定点整数在数轴上分布的点之间都是等距的吗?

答:是的。定点整数在数轴上的点总是在整数值上,即[…, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, …],相邻数据间隔总是1。

17. 为什么要引入浮点数表示?

答:因为定点数不能表示实数,而且表数范围小,所以,要引入浮点数表示。

18. 为什么浮点数的阶(指数)要用移码表示?

答:因为在浮点数的加减运算中,要进行对阶操作,需要比较两个阶的大小。移码表示的实质就是把阶加上一个偏置常数,使得所有数的阶码都是一个正整数,比较大小时,只要按高位到低位顺序比较就行了,因而,引入移码可以简化阶的比较过程。

19. 浮点数如何表示0?

答:用一种专门的位序列表示0,例如,IEEE 754单精度浮点数中,用0000 0000H表示+0,用8000 0000H表示-0。当运算结果出现阶码过小时,计算机将该数近似表示为0,称为机器0。

20. 现代计算机中采用什么标准来表示浮点数?

答:早期的计算机各自采用不同的浮点数表示格式,因而,在不同计算机之间进行数据交换时,就会发生数据不统一的问题。因此现代计算机中都采用IEEE 754标准来表示浮点数。

21. 为什么浮点数要采用规格化形式表示?

答:为了使浮点数能尽量多地表示有效位数,提高浮点数运算的精度,而且规格化形式具有唯一性。

22. 如何判断一个浮点数是否是规格化数?

只要看转换为真值后,其尾数的第一位是否一定是非零数。因此,对于原码编码的尾数来说,只要看尾数数值部分的第一位是否为1就行。

23. 浮点数表示的精度和数值范围取决于什么?

答:浮点数的精度取决于尾数的位数,而数值范围取决于阶码的位数。在浮点数总位数不变的情况下,阶码位数越多,则尾数位数越少。即表数范围越大,则精度越差(数变稀疏)。

24. 基数的大小对表数范围和精度有什么影响?

答:基数越大,则范围越大,但精度变低(数变稀疏)。

25. 在高级语言编程中,float和double型数据是怎么表示的?

答:现代计算机用IEEE 754标准表示浮点数,其中32位单精度浮点数就是float型,64位双精度浮点数就是double型。

26. 在高级语言编程中,long double型数据是怎么表示的?

答:long double型数据的长度和格式随编译器和处理器类型的不同而有所不同。例如,Microsoft Visual C++ 6.0版本以下的编译器都不支持该类型,因此,用其编译出来的目标代码中long double和double一样,都是64位双精度;在IA-32上使用gcc编译器时,long double型数据采用Intel x87 FPU的80位双精度扩展格式(1位符号位s、15位阶码e、1位显式首位有效位(explicit leading significant bit)j和63位尾数f)表示;在SPARC和PowerPC处理器上使用gcc编译器时,long double型数据采用相应的128位双精度扩展格式(1位符号位s、15位阶码e和112位尾数f,采用隐藏位,故有效位数为113位)表示。

27. C语言程序中,为什么关系表达式“123456789==(int)(float)123456789”的结果为“假”,而关系表达式“123456==(int)(float)123456” 和“123456789 == (int)(double)123456789”的结果都为“真”?

答:float类型对应IEEE 754单精度浮点数格式,有效位数只有24位(相当于有7位十进制有效位数);double类型对应IEEE 754双精度浮点数格式,有效位数有53位(相当于有17位十进制有效位数);int类型为32位整数,其有效位数为31位(最大数为2147483647,相当于10位十进制有效位数)。

整数123456789的有效位数为9位,转换为float型数据后会发生有效位数丢失,再转换为int型数据时,已经不是123456789了,所以,关系表达式“123456789==(int)(float)123456789”的结果为假。

数据改为123456后,有效位数只有6位,转换为float型数据后有效位数没有丢失,因而数据没变,再转换为int型数据时,还是123456,所以,关系表达式“123456==(int)(float)123456”的结果为真。

整数123456789的有效位数为9位,转换为double型数据后,不会发生有效位数丢失,再转换为int型数据时,还是123456789,所以,关系表达式“123456789==(int)(double)123456789”的结果为真。

28. 位数相同的定点数和浮点数中,可表示的浮点数个数比定点数个数多吗?

答:不是的。可表示的数据个数取决于编码所采用的位数。编码位数一定,则编码出来的数据个数就是一定的。n位编码最多只能表示2n个数,因此,对于相同位数的定点数和浮点数来说,可表示的数据个数应该一样多。但是,有时由于一个值可能有两个或多个编码对应,编码个数会有少量差异。

29. 如何进行BCD码的编码?

答:每位十进制数的取值可以是0,1,2,…,9这十个数之一,因此,每一个十进制数位必须至少由4位二进制位来表示。而4位二进制位可以组合成16种状态,去掉10种状态后还有6种冗余状态,从16种状态中选取10种状态表示十进制数位0~9的方法很多,可以产生多种BCD码方案。

编码方案可分为有权码和无权码两种。有权码指表示每个十进制数位的4个二进制数位(称为基2码)都有一个确定的权,8421码是最常用的十进制有权码;无权码指表示每个十进制数位的4个基2码没有确定的权。

30. 汉字的区位码、国标码和机内码有什么区别?

答:GB2312字符集由94行、94列组成,行号称为区号,列号称为位号,各占7位,共14位,区号在左、位号在右,构成汉字的区位码,它指出了该汉字在码表中的位置。

汉字的国标码是将区号、位号各加上32(即16进制的20H)后,再在前后各7位前加0。汉字的机内码需2个字节才能表示,可以在国标码的基础上产生汉字机内码,一般是将国标码的两个字节的第一位置1。例如,已知一个汉字的国标码为343AH,前后两个字节各减32(20H)得到区位码141AH(=343AH-2020H),所以区号为20(14H),位号为26(1AH),机内码为B4BAH。

31. MSB(LSB)表示最高(低)有效字节还是最高(低)有效位?

答:MSB的含义可能是最高有效字节(Most Significant Byte),也可能是最高有效位(Most Significant Bit),具体表示哪一个含义要看上下文。同样,LSB的含义可能是最低有效字节(Least Significant Byte),也可能是最低有效位(Least Significant Bit)。

32. 有时用“字”表示数据的宽度,一个“字”到底有多少位?

答:除了用比特(bit)和字节(Byte)来表示一个数据的宽度外,有时也用字(word)来表示数据宽度的单位。不同的计算机,其“字”的长度和组成不完全相同,有的由2个字节组成,有的由4个、8个甚至16个字节组成。

33. 一个“字”的宽度就是一个机器字长吗?

答:不是。机器字长是计算机的一个非常重要的指标。通常所谓的32位机器或64位机器,就是指机器的字长是32位或64位。一般情况下,机器字长定义为CPU中一次能够处理的二进制整数的位数,实际上就是CPU中整数运算数据通路的位数。

字作为信息宽度的计量单位,对于某个系列机来说,其字宽总是固定的。例如,在80x86系列中,一个字的宽度为16位,因此,32位是双字,64位是四字。在RV32I架构中,一个字的宽度为32位,16位为半字,32位为单字,64位为双字。

一个字的宽度可以不等于机器字长。例如,在Intel微处理器中,从80386开始就至少都是32位机器了,即机器字长至少为32位,但其字的宽度都定义为16位。