编码:隐匿在计算机软硬件背后的语言
文前
- 一种在信息传输过程中用来表述字母或数字的信号系统。
推荐序
- 大方无隅,大象无形,也就是老子所说“道”的至高境界。世界上最恢宏、壮丽的气派和境界,往往并不拘泥于一定的事物和格局,而是表现出“气象万千”的面貌和场景,科学知识的论述也是如此。
- 透过现象进而探索本质可以发现新事物;将复杂的事物简单化,可以发现解决问题的新方法。
- 为学日益,为道日损,损之又损,以至于无为,无为而无不为”
译者序
- 所谓经典,就是历尽岁月的洗涤,依然毫不褪色,然其光彩却历久弥新。
作者序
- 这本书其实是讲述计算机如何工作的
- 明喻与暗喻是文学描述中精妙的辅助手段,但它们常常掩盖了科学技术的真正光芒。
- 内存与存储器的区别其实是在逻辑层面上的,它体现着计算机体系结构的实际需求与存储器客观性能之间的矛盾,简单地说就是我们找不到一种同时具备这两种存储器所有优点的存储媒介,这些优点就包括存储速度块、存储容量大、非易失性等等。
- 计算机是二十世纪技术领域的“登峰造极之作”,它是一种值得欣赏、具有“美”学文化底蕴的人类伟大成果,这种“美”不需要明喻与暗喻的额外修饰。
- 计算机拥有与生俱来的层次化体系结构,这种结构的底层是晶体管,其顶层则是计算机显示器上所呈现的信息。
- 学习技术发展史的重要意义正在于此:追溯的历史越久远,技术的脉络就变得越清晰。因此,我们需要做的就是确定某些关键的历史阶段,在这些阶段,技术最天然、最本质的一面将清晰可见。
1 至亲密友
- 渴望交流本来就是人类最主要的天性之一。
- 众所周知,手电筒是为了让孩子们能够躲在被子下看书而发明的
- A”是闪一次,“B”是闪两次,“C”是闪三次,依此类推,“Z”就是闪26次。单词BAD可以用闪2次,闪1次,闪4次这样的一个组合来表示,而且在字符之间设置的小停顿使这个单词不至于被误认为是闪7次的字母“G”。另外,单词之间停顿可以稍长些。
- 莫尔斯电码(Morse Code)
- 在莫尔斯电码里,则有两种闪烁——短闪和长闪
- 当问及莫尔斯电码是如何工作的时候,人们并不会谈论“短闪”与“长闪”。相反,他们使用“点(dot)”和“划(dash)”,因为这是在打印纸上显示编码的一个便利方法。在莫尔斯电码里,字母表里的每个字母都与一个点划序列相对应,正如下表所示。
- 熟悉编码的本质对于深入理解计算机软硬件内部结构以及隐匿在其后的语言将大有裨益。
- 编码这个词的意思是指一种用来在机器和人之间传递信息的方式。换句话说,编码就是交流。
- 你可以说英语词汇就是一类编码。
- 对任何能听见我们的声音并理解我们所说的语言的人来说,我们发出的声音所形成的词语是一种可识别的编码。
- 对于那些失明的人,书面语言可以用布莱叶盲文(Braille)来替代
- 如果一种编码可以用在其他编码无法取代的地方,那么它就是一种有用的编码。
- 计算机不能直接处理人类的编码,因为计算机无法通过与人类的眼睛、耳朵、嘴巴和手指完全相同的方式来接收人类发出的信息。
- 简单且短促的编码,被分配给字母表中使用频率较高的字母,例如E和T
- 三个点、三个划,再加三个点就表示SOS,即国际求救信号。SOS不是一个缩写,这只是一个易于记忆的莫尔斯编码序列。
- 莫尔斯编码的一个缺点是,它没有区分大写字母和小写字母
- 事实上,两个不同的事物,只要经过适当的组合,就可以表示所有类型的信息,这的确是千真万确的。
2 编码与组合
- 似乎这些字母对应的“点-划”序列并没有什么规律。所以忘掉字母序列吧。或许根据编码中所包含点、划的多少来对其进行分组,是一个更好的组织这些编码的方法。
- 每个表格所含有的码字,可以看成是在前一张表格所包含的全部码字上再加一个“点”,或者再加一个“划”而组成的新码字。
- 码字的数目 = 2“点”和“划”的数目
- 首先,它确保了我们不会对不同的字母定义相同的码字。其次,通过这个表我们可以用尽可能短的码字来表示所有的字母,而避免产生编码长度上的浪费。
- 码字的数目 = 2编码的位数
- 莫尔斯码也被称作二进制码(Binary Code),因为这种编码的组成元素只有两个——“点”和“划”。
- 上面所做的关于二进制编码的分析工作,其实是数学的一个分支,称作“组合学”或“组合分析”
3 布莱叶盲文与二进制码
- 在布莱叶盲文中,每个在书写文字中用到的符号——具体来说就是字母、数字和标点符号——都被编码成为2×3的点码单元中的一个或者多个凸起的点
- 二级布莱叶盲文使用了很多缩写,以便于保存树型结构和提高阅读速度
- 表示字符串缩写“ble”的码字很重要,因为当它不是用来作为单词的一部分时,它的出现就意味着之后的码字应被译为数字。
- 它们改变了后面编码的意义——从表示字母到表示数字,又从表示数字回到表示字母。像这样的编码通常被称作“优先码”(precedence codes)或者“换档码”(shift codes)。它们改变着作用域内编码的含义,直到作用域结束。
4 手电筒的剖析
- 每一个原子又由三种粒子构成:它们分别是中子(neutron)、质子(proton)和电子(electron)
- 原子序数表明了这种元素一个原子的原子核中所含的质子数,(通常)同时也是一个原子所含的电子数。
- 原子之间可以通过化学的方式结合形成分子(molecules)。
- 电子可能从原子中脱离。这就是电流产生的原因。
- 质子和电子都具有带电荷(charge)的性质。质子有一个正电荷(+),电子有一个负电荷(-)。中子是中性的,因而不带电荷。
- 静电火花是电子运动引起的,是电子通过一个回路——从地毯传到你的身体,再回到鞋子中的过程所造成的。
- 原子核中的质子被一种力量束缚到一起,这种引力要强过同性电荷之间的斥力,我们称之为“强力”(strong force)
- 闪电是大量电子从一端快速地移动到另一端所形成的。
- 电路中,某原子所含有的一个电子逃逸到它相邻的下一个原子中,与此同时,这个原子又从相邻的上一个原子中获取一个电子,而失去电子的原子又会从与其相邻的一个原子获得电子,如此循环。电路中的电子不断地从一个原子移动到下一个原子,就形成了电流。
- 电池内的化学物质是经过研究精心选择的,它们之间的化学反应能够使多余的自由电子聚集到标负号“-”的那端(称为负极或者阴极),而在标有正号“+”的那端(称为正极或者阳极)则变得急需额外的电子。于是,化学能就被转化成了电能。
- 所有的电子,不管它们在哪里,都是完全一样的
- 并联后的电压是1.5伏,与每个电池的电压是一样的。或许灯泡仍能发光,但是肯定没有串联电池的灯泡亮。不过电池的使用寿命也将延长一倍。
- 电路为电池内的化学反应的进行提供了条件。电路把电子从电池的负极运走,然后转移到电池的正极。
- 电流可以通过空气传导(特别是潮湿的空气),不然的话我们就看不到闪电了。
- 如果原子在最外电子层中只含有1个电子,那么这个电子很容易逃逸,这就是易导电物质所需具备的特性。这些物质对于电流来说是“导通”的,因而被称做导体(conductor)。
- 与导电性相反的是阻抗性。有一些物质与其他的物质相比更不容易让电流通过,我们称其为电阻。如果一种物质有着很强的阻抗性——也就是说它几乎不能传导任何电流——它就被称为绝缘体(insulator)。
- 不过事实上只要有足够高的电压,任何的物质都是可以导电的。
- 导线越长,它的阻抗就越高。
- 导线越粗,它的阻抗就越低。
- 电压表征了电流做功的“势”(potential),也就是电势能的大小。不管电池是否被连接到电路中,电压都是存在的。
- 电流与流经电路的电子数有关。它的计量单位是安培,
- 它的电压E是1.5伏。它代表做功的势能,但是因为正负极通过空气也有连通,所以电阻(R所代表的物理量)非常非常大,也就是说,电流(I)等于1.5伏的电压除以一个极大的数。因而电流在这里几乎是0。
- 如果导线电阻较低的话,它将变热并且发光。这就是白炽灯发光的原理
- 如果暴露在空气中,钨丝将达到燃点并开始燃烧,但是在灯泡的真空泡室内,钨丝就会发出光亮。
- P = E×I
- 开关只能是闭合状态或断开状态。电流只能是有或者无。灯泡也只能是发光或不发光。就像莫尔斯和布莱叶发明的二进制码一样,这个简单的手电筒要么是开着的,要么是关着的。没有介于二者之间的状态。
5 绕过拐角的通信
- 这种接线方式被称为公用连接(common)
- 你不必非得用导线来完成电路的共用部分,你可以用其他的东西来代替导线。恰巧我们这儿有一个现成的大球,你可以用它来代替。这个大球直径近7900英里,由金属、岩石、水,以及有机质(其中大部分是没有生命的)组成。我们称这个巨大球体为“地球”。
- 截面越大导电性越好。一条很粗的导线,其导电性要远远好于一条细导线。这就是地球所拥有的优势。它实在是太大了。
- 地球是一个巨大的导体,但是我们也可以把它看做是电子的来源和储藏库。地球之于电子就恰如海洋之于水滴。地球是一个近乎无尽的电子之源,同时也是一个无比庞大的电子池。
- 但是它也有吸尘器的意思。我们把V想象成一个电子吸尘器,然后把地面想象成电子的海洋。电子吸尘器通过电路把电子从地下拉出来,让它们沿设计好的线路开始工作
- 零电势就像放置在地面上的砖一样——已经没有空间可以让它下落了。
- 在本章中,我们已在通信的演变中迈出了重要一步。之前我们使用莫尔斯码交流时,必须要在视线直视的范围里,并且要保证在手电筒光线可以传播的距离之内。
- 另一种解决方案是增加电压,使用更大电阻的灯泡。
- 尽管它只不过是个很简陋的装置,但是正是基于这个装置,整个计算机系统才被构建出来。
6 电报机与继电器
- 电报机的原理是很简单的:在线路的这一端采取一些措施,使线路的另一端发生某种变化
- 电磁铁上缠绕足够多的细导线,会产生足够强的电阻,能防止电磁铁产生短路现象
- 电报机的发明标志着现代通信的开始。
- 继电器与发声器很像,传进来的电流驱动电磁铁拉动金属杠,金属杠同时又作为一个开关的组成部分,而这个开关连接着电池和输出线路。通过这种方法,输入的比较弱的电流就被“放大”成了较强的输出电流。
- 继电器是一个意义非凡的设备。当然,它是一个开关,但是这个开关的闭合和断开并不是由人来操纵的,而是由电流控制的
7 我们的十个数字
- 这个星球上几乎所有人都用以下方式来书写数字:1 2 3 4 5 6 7 8 9 10这难道不就是数学被称做“通用语言”的理由么?
- 英语中Digit(数字)这个词同时也有手指、脚趾的意思,并且还有数字的意思,这并不是巧合。而five(五)和fist(拳头)这两个单词的拥有相同的词根也是同样的道理。
- 这里,字母I表示1,可以看做是一个划线或者一根伸出的手指。字母V像一只手,表示5。两个V是一个X,代表数字10。L是50。C来自单词centum,表示100。D是500。最后一个,M来自于拉丁文mille,意为1000。
- 其中最著名的就是波斯数学家穆罕默德·伊本穆萨·奥瑞兹穆(根据这个人的名字衍生出英文单词“algorithm”,算法),
- 阿拉伯数字系统不同于先前的数字系统,体现在以下三点。
- 阿拉伯数字系统是和位置相关的。也就是说,一个数字的位置不同,其代表数量也不同。
- 是的,就是0。小小的一个零无疑是数字和数学史上最重要的发明之一。它支持位置计数法,因此可以将25、205和250区分开来。0也简化了与位置无关的数字系统中的一些非常复杂的运算,尤其是乘法和除法。
- 记住任何数的0次幂都等于1。
8 十的替代品
- 当我们认识到,10可以表示两只鸭子,我们就可以解释开关、导线、灯泡和继电器(进一步推广到计算机)是如何表示数字的了。
- 任何一个以1开头而后面全是0的二进制数一定都是2的整数次幂。幂指数就等于这个二进制数中0的个数。
- 每次只要有一个二进制数位的值由1变到0,紧挨着的高位数字也会发生变化,而且其变化不是由0到1就是由1到0。
- 二进制数字系统还在算术与电子技术之间架起了一座桥梁
- 他决定创造一个新的、更短的词语来代替使用起来很不方便的五音节词——binary digit。他曾经考虑使用bigit和binit,但是最终他还是选用了这个短小、简单、精巧而且非常可爱的词——bit。
9 二进制数
- 比特被看做是组成信息块的基本单位。
- 用通信理论的术语来说,他运用了“冗余”(redundancy)来抵消噪声的影响。通信理论中,噪声(noise)是指影响通信效果的所有事物。
- 信息是指多个可能性中的一种。
- 所有可以被转换成对两种或多种可能性的选择的信息,都可以用比特来表示。
- 某一位或一连串比特位所表示的意义通常是和上下文有关的。
- 利用二进制表示信息的一个额外的好处就是我们可以清楚地知道我们是否已经想到了所有的可能性。
- 无论何时我们谈到比特,通常所指的都是一定数目的比特位。我们拥有的比特位数越多,所能表示的不同可能性就越多。
- 通用产品代码(UPC,Universal Product Code)
- 扫描仪只识别整个条形码的一条窄带,条形码做得很大是为了便于结算台的操作人员用扫描仪对准。
- 因此,整个UPC只不过是一串95位二进制数。
- 前3位通常都是101,这就是最左边的护线,它帮助计算机扫描仪定位。
- 接下来是一个5比特位的中间护线,这是一个固定的模式(始终是01010),它是一个内置式的检错码。如果计算机扫描仪没有在应有的位置找到中间护线,它就无法破解UPC码。这条中间护线是用来预防条形码被篡改或被印错的一种方法。
- 第一个数字(在这里是0)被称为数字系统符。0意味着这是一个常规的UPC。如果UPC出现在杂货店中那些需要称重的商品上,例如肉、农产品,这个编码就会是2。票券的UPC的第一个数字通常是5。
- 最后一个数字(在这里是7)称为模校验字符。
- 从根本来说,比特是数字。在用比特表示其他信息的时候我们所要做的就是计算有多少种可能性。这决定了我们需要的比特位数,以便每种可能性都可以分配到一个编号。
- 逻辑学是哲学和数学的奇特融合,其主要目的就是确定某个陈述是真还是假
10 逻辑与开关
- 亚里士多德的逻辑学基础是三段论法
- 传统代数的另一个特点就是,它是处理数字的
- 操作数不是数字而是类(class)。简单说,一个类就是一个事物的群体,它后来也被称为集合(set)。
- 在布尔代数中,符号“+”表示两个集合的并集。
- 在布尔代数中,符号“×”表示两个集合的交集
- 为了避免在传统代数与布尔代数间混淆,有时用符号“∪”和“∩”来代替“+”和“×”。
- 在布尔代数中,符号1表示“全集”
- 矛盾律指出事物不可能既是它本身,同时又是它的对立面。
- 如果S × M = M,结论就会是:只有苏格拉底会死,其他任何事物都是不死的!
- 你要做的这些实验将布尔代数与电路相融合,并且可以设计和制造利用二进制进行计算的计算机。
- 两个开关并联相当于布尔代数中的OR运算。
- 本来有些东西可以帮到巴贝奇的,那是什么呢?我们现在知道,那就是根据一台电报器来创建计算机,而非使用齿轮和杠杆来实现计算。 是的,就是电报器。
11 门
- 在逻辑学中,逻辑门的工作方式非常简单——让电流通过或阻止电流通过。
- 在计算机术语中,开关是一种输入设备(input device),输入是控制电路如何工作的信息
- 继电器像开关一样,可以串联或并联在电路中执行简单的逻辑任务。这种继电器的组合叫做逻辑门(logic gates)。
- 实际上,继电器是通过放大微弱信号来生成强信号的。
- 我们真正感兴趣的是继电器可以作为一个电流控制而非人工控制的开关。
- 连接继电器是建立逻辑门的关键。
- 只有当两个继电器都被触发的时候灯泡才会亮。这样两个继电器的串联被称为一个“与门”
- 与门的符号不仅仅代替了两个串联的继电器,而且还暗示着上面的继电器与电源相连,两个继电器都接地。
- 显而易见,当上面的开关或下面的开关闭合,灯泡都会发光,这里的关键词是“或”,因此这样的门被称为“或门”。电气工程师用如下符号表示或门。
- 这样的话,开关闭合,灯泡就会熄灭。以这种方式连接的继电器叫做反向器(inverter)。反向器不是逻辑门(一个逻辑门通常有两个或多个输入),尽管如此,它的用处还是很广。
- 一个门(或反向器)的输出可以作为一个或多个其他门(或反向器)的输入。但是两个或多个门(或反向器)的输出是不可以相互连接的。
- 这些结果恰恰与或门相反,这个门称为“或非门”,简称NOR,用以下符号表示。
- 这一结果和与门恰恰相反。这种逻辑门被称为与非门,或简称NAND。
- 缓冲器“没有什么作用”,它的输入与输出是相同的。
- 缓冲器还可以用于延迟一个信号。这是因为继电器需要一点时间——几分之一秒——才会被触发。
- 以后的电路会由缓冲器、反向器、四种基本逻辑门和其他由逻辑门组成的复杂电路(如2-4译码器)组成
- 带有两个反向输入的与门和或非门是等价的。
- 这两组等价关系就是摩根定律在电路中的实现。
- 摩根定律可以简单地表示为如下形式:
- 摩根定律是简化布尔表达式的一种重要手段,因此也可以用来简化电路。
12 二进制加法器
- 加法计算就是计算机要做的唯一工作。
- 一对二进制数相加的结果中具有两个数位,其中一位叫做加法位(sum bit),另一位则叫做进位位
- 利用与门可以计算两个二进制数加法的进位。
- 实际上这个电路有个专门的名称,叫做异或门,简写为XOR。
- 两个二进制数相加的结果是由异或门的输出给出的,而进位位是由与门的输出给出的
- 半加器没有做到的是将之前一次的加法可能产生的进位位纳入下一次运算。
- 全加器(FullAdder)
- 加法器的总体速度等于数字的位数乘以全加器器件的速度,这被称做行波进位(ripple carry,或脉冲进位)。更快的加法器运用了一个被称为“前置进位”的电路来提高运算的速度。
13 如何实现减法
- 在减法中没有进位,而是有借位——一种与加法存在本质区别的麻烦机制。
- 从一串9中减去一个数叫做对9求补数
- 这个式子与刚才描述过的用9的补数进行的计算是相同的。我们用两个减法和两个加法来替代一个减法,而在这个过程中避免了烦琐的借位。
- 在求对1的补数时,只需将原来的二进制数中的1变为0,将0变为1即可。因此对1求补数有时也会称为相反数(negation)或反码(inverse)
- 将8个异或门合并起来画成一个器件,称为求补器
- 这种标记方法称为10的补数(ten’s complement)。为了将三位负数转化为10的补数,我们用999减去它再加1。也就是说,对10求补数就是对9的补数再加1。
- 最高有效位(最左位)作为符号位(sign bit)。符号位中,1表示负数,0表示正数。
- 为了计算2的补数,则首先要计算1的补数,然后再加1。这等价于将每位取反再加1。
- 一般来说,如果两个操作数的符号相同,而结果的符号与操作数的符号不相同,这样的加法就是无效的。
- 现在,二进制数可以有两种不同的使用方法。二进制数可以是有符号的,也可以是无符号的。无符号的8位二进制数所表示的范围是0~255。有符号的8位二进制表示的范围是-128~127。无论是有符号的还是无符号的,数字本身是无法显示的。
14 反馈与触发器
- 反向器在本质上就是一个继电器,而继电器将状态取反以得到另一个状态是需要一点点时间的
- 我们把这种电路称为振荡器(oscillator)
- 振荡器又经常被称为时钟(clock),通过振荡进行计数也是一种计时方式。
- 振荡器从某个初始状态开始,经过一段时间又回到先前初始状态的这一段间隔定义为振荡器的一个循环(cycle),或者称为一个周期
- 一个循环所占用的时间就是该振荡器的周期(period)。
- 左边或非门的输出是右边或非门的输入,而右边或非门的输出是左边或非门的输入。这种连接方式我们称之为反馈(feedback)
- 究其原因可以发现这是由于左边或非门的输出一直为0。
- 当两个开关都断开时,电路有两个稳定态,这类电路统称为触发器(Flip-Flop)
- 触发器电路可以保持信息,它可以“记住”某些信息。
- 触发器和跷跷板有着很强的相似性。跷跷板也有两个稳定状态,它不会长期停留在不稳定的中间位置。通过观察跷跷板,我们很容易推测出哪边最后一次被压下来。
- 触发器的的确确是一种必不可少的工具。它们可以让电路“记住”之前发生了什么事情。
- R-S(Reset-Set,复位/置位)触发器
- R-S触发器最突出的特点在于,它可以记住哪个输入端的最终状态为1
- 这个电路称为电平触发的D型触发器,D(Data)表示数据端输入
- 这个电路也就是所谓的电平触发的D型锁存器,它表示电路锁存住一位数据并保持它,以便将来使用。这个电路也可以被称为1位存储器。
- 在电平触发器中,当时钟输入为0时,数据端输入的任何改变都不会影响输出;而在边沿触发器中,当时钟输入为1时,数据端输入的改变也不会影响输出。只有在时钟输入从0变到1的瞬间,数据端的输入才会影响边沿触发器的输出。
15 字节与十六进制
- 这8位比特流就是加法器、锁存器以及数据选择器的输入形式,同时它也是这些器件单元的输出形式。
- 8比特代表一个字节(byte)。
16 存储器组织
- 这种配置下的锁存器在有的资料中也被称为读/写存储器(read/write memory),但更普遍的叫法是随机访问存储器(Random Access Memory),或RAM(和单词animal发音类似)。
- RAM阵列的存储容量 = 2地址输入端的个数
- 随机访问存储器也被称为易失性(volatile)存储器。为了保证存储的数据不丢失,易失性存储器需要恒定的电流。
17 自动操作
- 用来累加多个数的锁存器称做累加器(accumulator)。
- 以这种方式使用的数字代码常常被称为指令码(instruction code)或操作码(operation code,opcode)。它们指示电路要执行的某种操作。
- 能否控制重复操作或者循环(looping)是计算机(computer)和计算器(calculator)的区别。
- 能够被处理器响应的操作码(比如Load指令和Store指令的代码10h和11h),称做机器码(machine codes),或机器语言(machine language)。
18 从算盘到芯片
- 锗元素和硅元素(以及一些化合物)被称为“半导体”(semiconductor),之所以称为“半导体”并不是因为它们的导电性能是导体的一半,而是因为它们的导电系数可以通过多种方式操控。
- 影响一个集成电路性能的最重要因素可以认为是传播时间(propagation time),也就是输入端发生变化引起输出端发生相应变化所需要的时间。
- 最大时钟频率(maximum clock speed),也称为主频,是影响处理器速度的决定性因素之一
20 ASCII码和字符转换
- 所有由符号所表示的字母和数字(Alphanumeric)都需要编码。具有这种功能的系统被称为字符编码集(Coded Character Set),系统内的每个独立编码称为字符编码(Character Codes)。
21 总 线
- 计算机中各部件按照功能被分别安装在两个或更多的电路板上。这些电路板之间通过总线(bus)通信。如果对总线做一个简单的概括,可以认为总线就是数字信号的集合,而这些信号被提供给计算机上的每块电路板。
22 操作系统
- 操作系统提供的第三个主要功能是让程序能够方便地访问计算机的硬件,操作系统提供的这种访问操作称为API(Application Programming Interface),即应用程序接口。