
《计算机是如何工作的人人都能懂的计算机软硬件工作原理》第一章 计算机的概念 阅读笔记 1前言很多软件开发方面的工作人员他们知道如何编写代码但是相当一部分人似乎并不了解计算机实际上是如何工作的。他们知道如何让计算机执行命令但并不理解幕后的情况。第1章 计算机的概念1.1 计算机的定义从一个基本问题开始什么是计算机当人们听到 “计算机” 这个词的时候大多数人会想到笔记本计算机或台式计算机。这是本书会涉及的一类设备但是让思考角度更广一些。想一想智能手机。智能手机当然也是计算机智能手机可完成 PC 上完成的操作。事实上对现在的很多人来说智能手机是他们主要的计算机设备。如今的大多数计算机用户还依赖互联网互联网由服务器支持服务器是另一类计算机。每当浏览网站或使用连接到互联网的 app 时其实都在与一个或多个连接到全球网络的服务器进行交互。电子游戏机、智能手表、智能电视……这些都是计算机计算机是可以被编程并执行一组逻辑指令的电子设备。有了这个定义就会发现许多现代设备实际上都是计算机1.2 模拟和数字你可能听说过计算机被描述为数字设备。这与诸如机械时钟的模拟设备相反。但是这两个术语究竟是什么意思理解模拟与数字之间的差异是理解计算机的基础所以仔细来看看这两个概念。1.2.1 模拟方法看看你的周围并挑选出一个对象。问问自己它是什么颜色的有多大有多重回答这些问题其实就是在描述这个对象的属性或者说数据。现在再挑一个不同的对象并回答同样的问题。如果对更多的对象重复这个过程你就会发现其中的每个问题都有无数潜在的答案。你可以选择一个红色的对象、一个黄色的对象或一个蓝色的对象甚至是三原色混合颜色的对象。这种类型的变化不仅适用于颜色。对于给定的属性在这个世界的各个对象之间所存在的属性变化可能是无限的。口头描述对象是一回事但是想更精确地测量它的一个属性则是另一回事。例如如果想测量一个对象的重量需要把它放到秤上。从秤上读取该数字就得到了该对象的重量。这种测量很常见但是再思考一下是如何测量这个数据的。秤上指针的位置不是实际的重量它是重量的一种表示形式。指针指向的数字刻度轴提供了一种简单的方式将代表重量的指针位置和重量的数值进行转换。换句话说虽然重量是对象的一个属性但在这里可以通过别的东西指针在数字刻度轴上的位置来理解这个属性。指针的位置会按照秤上对象的重量成比例地变化。因此秤可以作为一种模拟方法可以通过秤的指针在数字刻度轴上的位置来理解对象的重量。这就是把这种测量方法称为模拟方法的原因。模拟测量工具的另一个例子是水银温度计。水银的体积会随着温度的上升而增大。温度计制造商利用这个特性把水银放进玻璃管中玻璃管上不同的刻度对应不同温度下水银的预期体积。因此水银在玻璃管中的位置就可以用来表示温度。注意对于这两个例子秤和温度计当进行测量时可以把仪器上的刻度转换成特定的数值。但是从仪器上读到的值只是一个近似值。指针和水银的真实位置可以是仪器最小刻度之间的任何地方向上或向下舍入到最近的刻度值。所以虽然看上去这些工具似乎只能产生一组有限的测量值但这种限制来源于数字转换而不是模拟方法本身。在人类历史的大多数时间里人类都是用模拟方法进行测量的。但是人们并不仅仅使用模拟测量方法他们还设计了用模拟方式存储数据的巧妙方法。留声机唱片使用沟槽作为已录制音频的模拟表示。沟槽的形状随其路径而变化变化方式与音频波随时间的变化相对应。沟槽不是音频但它是原始声音波形的模拟。胶片相机与之类似它把胶片短暂地曝光于来自相机镜头的光线从而导致胶片发生化学变化。胶片的化学性质不是图像但它表示了所捕获的图像是图像的模拟。1.2.2 数字化所有这些与计算机有什么关系呢事实证明数据的模拟表示对于计算机来说是难以处理的。模拟系统类型是如此丰富多样以至于创造一个能模拟全部这些系统的通用计算设备几乎是不可能的。例如创造一台能测量水银体积的机器与创造一台能读唱片沟槽的机器是完全不同的任务。此外计算机还需要能高度可靠和准确地表示某些类型的数据。数据的模拟表示难以精确测量而且精度在被复制的时候可能失去保真度。计算机需要一种方式来表示所有类型的数据且格式能被准确地处理、存储和复制。如果不想把数据表示为可能无限变化的模拟值那么该怎么办呢可以采用数字方法。数字系统把数据表示成一系列符号符号的种类是有限的。现在这个描述听起来有点格式化和令人困惑接下来结合实践理解。在几乎所有的现代计算机中数据都被表示为两个符号的组合这两个符号就是 0 和 1。虽然数字系统可以使用两个以上的符号但是增加符号会提高系统的复杂度和成本。只采用两个符号能简化硬件并提高可靠性。大多数现代计算机中的所有数据都是用 0 和 1 的序列来表示的。从此刻开始当谈及数字计算机时你可以认为我说的系统只处理 0 和 1而不是其他一些符号集。有一点需要强调计算机上所有的数据都是以 0 和 1 的形式存储的。你最近用智能手机拍的一张照片也是如此吗是的设备把这张照片存储为 0 和 1 的序列。从网上下载的歌曲呢0 和 1 的序列。在计算机上编写的文档呢0 和 1 的序列。安装的 app 呢也是 0 和 1 的序列。访问的网站呢还是 0 和 1 的序列。只用 0 和 1 便可表示自然界中的无限值这听起来似乎是有局限性的。怎么把音乐录音或精细的照片精简为 0 和 1 呢很多人发现用有限的“词汇” 表示复杂的思想是违反直觉的。这里的关键是数字系统使用的是 0 和 1 的序列。例如一张数字照片通常是由数百万个 0 和 1 组成的。那么这些 0 和 1 到底是什么呢你可能会看到其他用来描述这些 0 和 1 的术语如假和真、关和开以及低和高等。这是因为计算机不能按字面意思来存储数字 0 或 1。它存储的是一系列的项 (entry)每一项都只有两种可能的状态。每一项都像电灯的开关一样要么开要么关。实际上这些 0 和 1 的序列是以各种方式存储的。在 CD 或 DVD 上0 和 1 是以盘片上凸起 (0) 或平坦 (1) 的形式表示的。在闪存驱动器中1和 0 以电荷的形式存储。硬盘驱动器通过磁化与否来存储 0 和 1。正如你将在第 4 章看到的数字电路用电平来存储 0 和 1。在继续介绍后面的内容之前关于 “模拟” 最后需要注意的一点是它通常只用来表示 “非数字”。例如工程师可能会说 “模拟信号”其含义是信号是连续变化的不符合数字值特性。换句话说它是非数字信号。1.3 数字系统到目前为止已经确定计算机是处理 0 和 1 的数字机器。对许多人来说这个概念看起来有些奇怪他们习惯用 0 到 9 来表示数字。如果限制自己只使用 2 个符号而不是 10 个符号那怎么表示大的数字呢要回答这个问题需要回顾一下小学的数学知识数字系统。1.3.1 十进制数通常用所谓的十进制位值记数法 (decimal place-value notation) 来书写数字。位值记数法或按位记数法是指被书写数字的每个位置都代表一个不同的数量级十进制或以 10 为基数是指数量级的因数是 10每个位置可以是 09 这十个不同符号中的一个参见下图中的位值记数法示例。在图中该数字用十进制位值记数法写作 275。5 在个位上代表它的值是 5×15。7 在十位上代表它的值是 7×1070。2 在百位上代表它的值是 2×100200。所有位置代表的值的总和为 570200275。很容易吧你可能在一年级就明白了。但是仔细研究一下为什么最右边的是个位为什么下一个位置是十位这是因为采用的是十进制或者以 10 为基数所以每个位置的权重就是 10 的幂如下图所示最右边的位置是 10 的 0 次幂也就是 1下一个位置是 10 的 1 次幂也就是 10再下一个位置是 10 的 2 次幂也就是 100。如果需要用十进制表示大于999的数就在左边再增加一位即千位它的权重等于 10 的 3 次幂 (10×10×10)也就是 1000。继续按这个模式扩展就可以得到任意大的数字。已经知道了为什么不同的位置有不同的权重继续深挖一下为什么每个位置都使用符号 09当使用十进制时只有10个符号因为根据定义每个位置只能表示 10 个不同的值。09 是目前所使用的符号但其实可以使用任何一组 10个具有唯一性的符号这其中的每个符号对应一个特定的数值。大多数人喜欢把以 10 为基数的十进制系统作为数字系统。据说这是因为人类有 10 个手指和 10 个脚趾但不管理由是什么现代世界的大多数人阅读、书写和思考数字时都使用十进制。当然这只是集体选择用来表示数字的一种约定。正如前面提到的这种约定不适合应用在计算机上计算机只使用了两个符号。接下来看看在限定两个符号的同时如何运用位值系统。1.3.2 二进制数只包含两个符号的数字系统是以 2 为基数或是二进制的。二进制系统仍然是位值系统所以其基本机制与十进制系统相同但是它也有一些变化。首先每个位置的权重是 2 的幂而不是 10 的幂。其次每个位置只能是 2 个而不是 10 个符号中的一个这两个符号就是 0 和 1。下图举例说明了如何用二进制表示一个数。下图中给出了一个二进制数101。对你来说这个数看起来可能挺像一百零一但在二进制中它实际表示的是 5如果你想口头表达出来那么可以读作 “二进制一零一”。就像十进制一样每个位置都有一个等于基数各次幂的权重。当基数等于 2 时最右边的位置是 2 的 0 次幂值为 1下一个位置是 2 的 1 次幂值为 2再下一个位置是 2 的 2 次幂值为 4。另外和十进制相同的是要得到总的数值就要用每个位置上的符号乘以位值权重然后再把结果加起来。所以从右边开始就有 (1×1)(0×2)(1×4)5。很快你就会发现同时处理十进制和二进制会造成混淆因为一个像 10 这样的数在十进制中表示的是 10在二进制中表示的是 2。本书从现在开始如果有混淆的苗头那么二进制数将用 0b 开头。之所以选择 0b 作为前缀是因为有几种编程语言采用了这种方法。前导字符 0 表示数字值b 是二进制 (binary) 的缩写。例如0b10 代表二进制的 2而 10 没有前缀则代表十进制的 10。1.4 位和字节十进制数中的单个位或符号称为数字 (digit)。像 1247 这样的十进制数就是一个四位数。类似地二进制数中的单个位或符号称为位 (bit)。每个位都可以是 0 或 1。像 0b110 这样的二进制数就是一个 3 位数。单个位能传递的信息很少要么关要么开要么 0要么 1。需要用位序列来表示更复杂的东西。为了让这些位序列更易于管理计算机把 8位分成一组----称为字节。下面是一些位和字节的例子因为都是二进制所以省略了前缀 0b1 这是一个位0 这还是一个位11001110 这是一个字节或8位00111000 这也是一个字节10100101 这还是一个字节0011100010100101 这是两个字节或16位注意4 位数即半个字节有时被称为半字节写为 nybble 或 nyble。一个字节能存储多少数据呢考虑这个问题的另一个思路是用 8 位可以得到多少个不同的 0/1 组合在回答这个问题之前用 4 位来说明这样更容易看明白。在表中列出了 4 位数中所有可能的 0/1 组合还给出了与该数字对应的十进制表示。如表所示可以用 4 位数表示 16 个不同的 0/1 组合范围从十进制的 0 到 15。查看位的组合列表有助于说明这一点但是还有几种方法可以解释这个问题而不用枚举每种可能的组合。二进制十进制00000000110010200113010040101501106011171000810019101010101111110012110113111014111115通过把所有位都设置为 1可以确定 4 位能表示的最大数字即 0b1111。这就是十进制的 15。如果把表示的 0 也算上那么得到的总数就是16。另一种简便的方法是取 2 的位数次幂这里位数为 4那么总共有 2^42×2×2×216 个 0/1 组合。研究 4 位数是一个好的开始不过前面谈论的是字节它有 8 位。按照上面的方法可以列出全部的 0/1 组合但是跳过这一步直接采用简便方法计算 2 的 8 次方可以得到 256这就是一个字节所含的不同组合的数量。现在知道了一个 4 位数可以有 16 种 0/1 组合一个字节可以有 256 种组合。这和计算机有什么关系呢假设一个计算机游戏有 12 个关卡那么这个游戏只需要 4 位就可以轻松地保存当前关卡号。如果游戏有 99 个关卡那么 4 位就不够用了4 位最多只能表示 16 个关卡但是一个字节就能很好地处理 99 个关卡的需求。计算机工程师有时需要考虑用多少位或多少字节来保存数据。1 个字节的大小是 8 位。1.5 前缀倍数词头大于 1因数符号中文名英文10³⁰Q昆[它]quetta10²⁷R容[那]ronna10²⁴Y尧[它]yotta10²¹Z泽[它]zetta10¹⁸E艾[可萨]exa10¹⁵P拍[它]peta10¹²T太[拉]tera10⁹G吉[咖]giga10⁶M兆mega10³k千kilo10²h百hecto10¹da十deca分数词头小于 1因数符号中文名英文10⁻¹d分deci10⁻²c厘centi10⁻³m毫milli10⁻⁶μ微micro10⁻⁹n纳[诺]nano10⁻¹²p皮[可]pico10⁻¹⁵f飞[母托]femto10⁻¹⁸a阿[托]atto10⁻²¹z仄[普托]zepto10⁻²⁴y幺[科托]yocto10⁻²⁷r柔[托]ronto10⁻³⁰q亏[科托]quecto有了这些前缀如果想说 “30亿字节”就可以用缩写 3GB 表示。或者如果想表示 4000 位就可以说 4kb。注意B 代表字节b 代表位。你会发现这种约定一般用于表示位和字节的数量可惜的是这在技术上通常也是不正确的。其原因在于在处理字节时大多数软件实际是以2 为基数的而不是以 10 为基数如果计算机告诉你文件的大小为 1 MB那么它实际有1048576 字节这约等于 10^6但不完全等于。看起来像是个奇怪的数不是吗这是因为是按十进制来看的。在二进制中同样的数字表示为 0b100000000000000000000它是 2^20。1 M 表示二进制数 100000000000000000000换算为十进制为 1048576。表展示了在处理字节时如何解释 SI 前缀。前缀名前缀符号值以 2 为基数太T1,099,511,627,7762⁴⁰吉G1,073,741,8242³⁰兆M1,048,5762²⁰千K1,0242¹⁰位和字节另一个会混淆的地方和网络传输速率有关。在计算机中采用的是二进制如果计算机告诉你文件的大小为 1 MB那么它实际有1048576 字节1 M 表示二进制数 100000000000000000000换算为十进制为 2^20 等于 1048576。互联网服务提供商通常以每秒位数作为单位采用的是十进制。因此如果互联网连接传输速率为 50Mb/s那么就意味着每秒只能传送大约 6MB 数据。也就是说每秒 50 Mb 等于每秒 50000000 位除以每字节 8 位得到每秒 6250000 字节在计算机中1 MB 等于 2^20 字节用 6250000 除以 2^20得到每秒大约 6 MB。二进制数据的SI前缀为了解决由前缀多义性导致的混乱2002 年引入了一组新的前缀在 IEEE 1541 标准中用于二进制场景。当处理 2 的幂时Ki 用于代替 KMi 用于代替 M以此类推。这些新的前缀对应于以 2 为基数的值用于之前不正确使用旧前缀的场合。例如由于 KB 可能被解释为 1000 或1024 个字节因此这个标准就建议使用 KiB 来表示 1024 个字节而 KB 则保留其原始意义即 KB 等于 1000 个字节。这看上去是个好主意但是直到撰写本书的时候这些符号还未得到广泛使用。表列出了新的前缀及其含义。前缀名前缀符号值以 2 为基数太Ti1,099,511,627,7762⁴⁰吉Gi1,073,741,8242³⁰兆Mi1,048,5762²⁰千Ki1,0242¹⁰这个差异很重要因为在实践中大多数软件在显示文件大小的时候使用的是旧的 SI 前缀但在计算大小的时候却是以 2 为基数的。换句话说如果你的设备说一个文件的大小是 1 KB那么它的意思是说有 1024 字节。此外存储设备制造商在为它们的设备容量打广告的时候则倾向于以 10 为基数来表示容量大小。这就意味着广告宣称为 1TB 的硬盘可能包含 10^12 字节但是当你把它连接到计算机时则会显示其容量大约为 931 GB10^12 除以 2^30。由于新前缀使用率不高因此本书将继续使用旧的 SI 前缀。宣称 1 TB 的硬盘为什么插在计算机上实际显示只有大约 931 GB。硬盘厂商在宣传时使用的是 10 进制而计算机实际使用的是 2 进制10 进制下10 TB 等于 10^12 字节2 进制下1 GB 等于 2^30 字节10^12 字节除以 2^30 字节大约为 931 GB。宣称 50Mb/s 的网速为什么每秒实际传输大约只有 6MB 数据。移动联通电信公司宣传的网速采用的是十进制而计算机实际使用的是二进制。也就是说每秒 50 Mb 等于每秒 50000000 位除以每字节 8 位得到每秒 6250000 字节在计算机中1 MB 等于 2^20 字节用 6250000 除以 2^20得到每秒大约 6 MB。1.6 十六进制在结束用二进制思考这个话题之前还要提一下另一个数字系统十六进制。“正常的” 数字系统是十进制系统或者说以 10 为基数的系统。计算机使用的是二进制系统即以 2 为基数的系统。十六进制系统以 16 为基数十六进制缩写为 hex系统也是一种位值系统其中的每个位置都表示 16 的幂每个位置的符号都可以是 16 个符号中的一个。和所有的位值系统一样最右边的位置仍是 1 的位置其左边第一位是 16 的位置然后是 256(16×16) 的位置之后是 4096(16×16×16) 的位置以此类推。非常简单但是每个位置可以放置的 16 个符号是哪些呢通常有表示数字 09 的 10 个符号。要表示其他值还需要另外 6 个符号。可以随机选择一些符号比如 、、#但是这些符号没有明显的顺序。相反采用 A、B、C、D、E、F大小写均可才是标准做法。在这个方案中A 代表10B 代表11以此类推直到 F它代表的是 15。这样是对的需要一些符号来表示从 0 到基数减 1 的数字。因此其他 6 个符号是AF。为了清晰起见标准的做法是用前缀 0x 来表示十六进制。表列出了 16 个十六进制符号以及它们十进制和二进制的值。十六进制符号十进制二进制000000110001220010330011440100550101660110770111881000991001A101010B111011C121100D131101E141110F151111当需要表示的值大于十进制的 15 或十六进制的 0xF 时会怎么样呢和十进制一样增加一位。0xF 的后面是 0x10这就是十进制的 16。然后是 0x11、0x12、0x13以此类推。现在看一下图便可以看到更大的十六进制数 0x1A5。图给出了十六进制数 0x1A5它的十进制值是多少呢最右边位置的值为 5旁边位置的权重为 16位置上有个 AA 代表十进制的 10因此中间位置为 16×10160。最左边位置的权重为 256位置上有个 1所以这个位置的值为 256。总数值用十进制表示为 5160256421。为了强调这一点这个例子展示了像 A 这样的新符号是如何根据其出现的位置而有不同的值的。0xA 是十进制的 100xA0 则是十进制的 160因为 A 出现在 16 的位置上A 表示十进制的 10。现在你可能会说“太棒了但是这有什么用呢”我很高兴你有这样的疑问。计算机不使用十六进制大多数人也不使用。但是十六进制对于那些要处理二进制数的人来说却是很有用的。使用十六进制有助于克服处理二进制数的两个常见困难。首先大多数人都不擅长阅读较长的 0/1 序列。对于人类而言处理16个或更多的位很困难且容易出错。其次尽管人类善于处理十进制数但十进制和二进制之间的转换并不容易。对于大多数人来说很难在看到一个十进制数后就能很快说出该数用二进制表示时哪些位是 1哪些位是 0。但是将十六进制转换成二进制要简单得多。表给出了 2 个 16 位二进制数及其对应的十六进制与十进制表示。注意为了清晰起见在二进制数值中添加了空格。16 位二进制数十六进制十进制1111 0000 0000 1111F00F61,4551000 1000 1000 0001888134,945先看表中的例 1。它的二进制表示是个明确的序列前 4 位全是 1之后的 8 位全是 0最后的 4 位全是 1。从十进制角度来看这个序列是模糊的。从 61455 来看完全不清楚哪些位是 0哪些位是 1。而十六进制序列是二进制序列的镜像。第一个十六进制符号是 F即二进制中的 1111之后的两个十六进制符号是 0最后一个十六进制符号是 F。接着看例 2前 3 个 4 位组都是 1000最后一个 4 位组是 0001。这在二进制中看着很简单但在十进制中看着就很难了。十六进制提供了更清晰的表示十六进制符号 8 对应于二进制的 1000十六进制符号 1 对应于 0001我希望你能看出一种模式二进制中每 4 位对应于十六进制中的 1 个符号。如果你还记得 4 位是半个字节的话那么便可知道一个字节可以表示成两个十六进制符号。一个 16 位的二进制数可以用 4 个十六进制符号表示一个 32 位的二进制数用 8 个十六进制的符号表示以此类推。以图中的 32 位二进制数为例。在图中可以按每次半字节的节奏来消化这个相当长的数字这是用十进制表示的相同数字 (2320695040) 无法办到的。由于二进制与十六进制之间的转换相对容易因此许多工程师通常会同时使用它们只在必要时才会转换成十进制。后续在有意义的情况下本书将会使用十六进制。1.7 总结本章讨论了一些计算机的基本概念。你知道了计算机是可以通过编程来执行一组逻辑指令的电子设备。你还了解了现代计算机是数字设备而不是模拟设备并明白了二者之间的区别模拟系统是那些用变化范围较大的值来表示数据的系统而数字系统则是用符号序列表示数据的系统。之后探究了现代数字计算机是如何只依赖于 0 和 1 两个符号的并了解了仅含有两个符号的数字系统即以 2 为基数的系统或二进制系统。还介绍了位、字节和标准 SI 前缀利用它们你可以更容易地描述数据的大小。最后你了解到对使用二进制的人来说十六进制非常有用的原因。第 2 章将更仔细地研究二进制是如何用于数字系统的。将介绍如何使用二进制来表示各种类型的数据以及二进制逻辑是如何工作的。