---
schema_version: "library-reader-v1"
source_type: "original_book"
title: "编码 隐匿在计算机软硬件背后的语言"
author: null
edition: null
publisher: null
year: null
isbn: "9787121181184"
library_document_id: "38270854-596f-4a26-8183-db8c968c6020"
source_sha256: "249786274d83909f0bddc34d77f81ed8f0b14d1eac8843c772a37a3ecbfe2cfc"
pdf_physical_page_count: 438
pdf_physical_page_index_base: 0
range_start: 220
range_count: 10
html_url: "https://workshop.closeclaw.top/api/ai/read/38270854-596f-4a26-8183-db8c968c6020?start=220&limit=10"
markdown_url: "https://workshop.closeclaw.top/api/ai/read/38270854-596f-4a26-8183-db8c968c6020.md?start=220&limit=10"
previous_url: "https://workshop.closeclaw.top/api/ai/read/38270854-596f-4a26-8183-db8c968c6020.md?start=210&limit=10"
next_url: "https://workshop.closeclaw.top/api/ai/read/38270854-596f-4a26-8183-db8c968c6020.md?start=230&limit=10"
---

# 编码 隐匿在计算机软硬件背后的语言

> 页码规则：PDF_PHYSICAL_PAGE_INDEX 是从 0 开始的权威文件物理页索引；PRINTED_PAGE 是页面中识别出的印刷页码，可能为空，二者不得混用。

## PDF_PHYSICAL_PAGE_INDEX=220 | PRINTED_PAGE=204

为了能圆满完成任务，我们需要另外一款电路元件，而且这款元件与8-1选择器功能类似，但它的作用正好相反。我们所说的正是3-8译码器（3-to-8Decoder)。前面的章节中我们曾学习过一个简易的数据译码器(Data Decoder)——在第11章中为了选择喜欢的猫咪的毛色，我们把开关以一定方式进行连接使其具有选择功能。

3-8译码器的输出端口共有8个。在任何时刻，译码器只会有一个锁存器的输出为1，其余均为 $\mathbf { 0 } _ { \circ }$ 每一个输出端的结果都是由 $\mathbf { S } _ { 0 } , \ \mathbf { S } _ { 1 } , \ \mathbf { S } _ { 2 }$ 这三个信号的排列组合决定的。而数据的输出和输入一致，如下图所示。

编码隐匿在计算机软硬件背后的语言

204

## PDF_PHYSICAL_PAGE_INDEX=221 | PRINTED_PAGE=205

我想再次强调一遍：注意从上往下数的第6个与门，它的输入包括 ${ \bf { S } } _ { 0 }$ 、 $\overline { { \mathsf { S } } } \imath$ 、 $\mathbf { S } _ { 2 \mathsf { c } }$ 没有任何一个与门具有和它相同的三个输入。在这种情况下，如果选择输入端为101，则除了 $\mathbf { O } _ { 5 }$ 要根据情况进行判定外，其余与门输出都为 $0 _ { \circ }$ 这个时候，若数据端输入为0，则$\mathrm { \bf O } _ { 5 }$ 随之输出为 $\mathbf { 0 } ;$ 相应的，若数据端输入为1，则 $\mathbf { O } _ { 5 }$ 输出为1。译码器的逻辑表可以如下表所示。

将8个锁存器加入到电路就形成了完整的系统。

16 存储器组织

205

## PDF_PHYSICAL_PAGE_INDEX=222 | PRINTED_PAGE=206

值得注意的是，译码器和选择器具有相同的选择信号，在上图中这三个信号一起被称为地址端口（Address)。地址的作用就像我们平时使用的邮箱号，长度为三位的地址决定了8个锁存器中的哪一个将被引用。在3-8译码器的输入端，地址起到了决定哪些锁存器可以被写操作端的信号触发来保存数据的作用。在输出端（图的下半部分），8-1选择器通过地址来选择8个锁存器中的一个，最后将其输出。

这种配置下的锁存器在有的资料中也被称为读/写存储器（read/write memory)，但更普遍的叫法是随机访问存储器（Random Access Memory)，或 RAM(和单词 animal 发音类似)。可以认为我们讨论的这种存储器是可存储8个独立比特的RAM，它的简化结构图如下所示。

上图所示的电路之所以能够被称为存储器是因为它可以保存信息。而能够被称为读/写存储器是因为它不仅可以在每个锁存器中存储新的数据（可以把这种功能称为写数据)，而且我们还可以检查每个锁存器都保存了什么数据（可以把这种功能称为读数据）。之所以可以被称为随机访问存储器，是因为读写操作很自由，我们只需要改变地址及相关的输入，就可以从8个锁存器中读出或写入需要的数据。相比于其他的顺序型的存储器这种存储器在使用时有一定的限制，如果想要读取地址为101的数据，必须先把地址为100的数据读取出来。

将RAM进行特殊的配置可形成 RAM阵列（Array)，我们所讨论的这种 RAM阵列以8×1（读做8乘1）的方式组织起来。阵列以1比特作为存储单位，共存储8个单位的数据。所以这个RAM阵列中能存储的位数等于8与1的乘积。

编码—隐匿在计算机软硬件背后的语言

206

## PDF_PHYSICAL_PAGE_INDEX=223 | PRINTED_PAGE=207

RAM阵列的组合形式多种多样。比如我们可以通过共享地址的方式可以把两个8×1的RAM阵列连接起来，如下图所示。

我们把这两个 8×1的 RAM阵列的地址和输出都分别看成一个整体，这样就得到了个8×2的RAM阵列，如下图所示。

这个RAM阵列可存储的二进制数依然是8个，但每个数的位宽为2位。

我们还可以把两个8×1的RAM阵列看做是两个锁存器，使用一个2-1选择器和个1-2译码器就可以把它们按照单个锁存器连接方式进行集成，下面给出了这种方案的电路图。

16 存储器组织

207

## PDF_PHYSICAL_PAGE_INDEX=224 | PRINTED_PAGE=208

“选择”端之所以连接到译码器和选择器，主要作用是在两个8×1RAM阵列中选择一个，本质上它扮演了第4根地址线的角色。因此这种结构实质上是一种16×1的RAM阵列，如下图所示。

上图所示的RAM阵列存储容量为16个单位，每个单位占1位。

RAM阵列的存储容量与其地址输入端的数量有直接的联系。在没有地址输入端的情况下（只有1位锁存器和8位锁存器的情况），只能存储1个单位的数据；当存在1个地址输入端时，可以存储2个单位的数据；有两个地址输入端时，可以存储4个单位的数据；有3个地址输入端时，可以存储8个单位的数据；有4个地址输入端时，可以存储16个单位的数据。我们可以把它们之间的关系归纳成如下等式：

编码隐匿在计算机软硬件背后的语言

208

## PDF_PHYSICAL_PAGE_INDEX=225 | PRINTED_PAGE=209

前面已经向大家演示了怎么搭建小型RAM阵列，你可能会问：为什么不搭建一个大规模的RAM阵列呢？就像下面这样。

上图所示的RAM阵列可存储8192个比特的信息，每8个比特为一组，共分为1024个组。因为2的10次方恰好是1024，所以地址端共有10个输入端口。电路还包括8位的数据输入端和8位的数据输出端。

从专业的角度来讲，这个RAM阵列的存储容量为1024个字节。就好比一个邮局放置了1024个邮箱，而每个邮箱里面都可以存放1字节大小的邮件（希望不是垃圾邮件）。

1024字节通常简称为1千字节(kilobyte),1K这种称呼不可避免地要引起许多混淆。其中它的前缀kilo（源于希腊文khilioi，意思为1000)，经常在公制系统中用到。比如1千克( kilogram)代表着 1000 克(grams)；1 千米(kilometer)代表着 1000 米(meter)。有所不同的是，这里所说的1千字节却代表着1024个字节——并非1000个字节。

它们之间不同的根本原因在于公制系统是基于10的幂的计数系统，而计算机采用的是基于2的幂的计数系统，它们之间没有交集。比如10的幂为10、100、1000、10000、100000等，而2的幂为2、4、8、16、32、64等。我们可以证明不存在一对整数a和b使得10的a次幂与2的b次幂相等。

但是偶尔也会碰见非常接近的数字。事实的确如此，1000十分接近1024，用数学化的描述方法可以称这种关系为“约等于”，这样我们可以得到相应的数学表达式：

$$
2 ^ { 1 0 } \approx 1 0 ^ { 3 }
$$

这个表达式并非空穴来风，它真正的意义在于表明2的某次幂和10的某次幂几乎相等。我们利用这一巧合可以很方便地把1024个字节的存储空间用1千字节来表示。

16 存储器组织

RAM 阵列的存储容量 = 2 地址输入端的个数

209

## PDF_PHYSICAL_PAGE_INDEX=226 | PRINTED_PAGE=210

千字节可以简写为 $\mathbf { K } \mathbf { B } _ { \circ }$ 这样我们可以说前面所讲过的那个RAM阵列存储能力为1024个字节，也可以说成是1KB。

绝不能认为1KB的RAM阵列的存储能力为1000字节，它实际上是大于1000字节，是1024个字节，为了准确而清晰地表达你脑海中的数据，我们可以使用“1KB””或“1千字节”这两种通用的表述方式。

存储容量为1KB的存储系统由8个数据输入端、8个数据输出端和10个地址输入端所组成。由于这些字节是由10个地址输入端来标识和访间的，所以这种RAM阵列存储容量为 $2 ^ { 1 0 }$ 个字节。如果我们再加上一条地址线，它的存储容量将变成原来的两倍。下面的公式表示了存储容量的翻倍的过程。

$$
{ \begin{array} { r l } & { 1 \times \mathbf { B } - 1 0 2 4 8 - 2 ^ { 1 0 } 8 - 1 0 ^ { 7 } 8 } \\ & { 2 \times \mathbf { B } - 2 0 4 8 8 \mathbf { B } - 2 ^ { 1 1 } \mathbf { B } } \\ & { + 4 \mathbf { K } 8 - 4 0 9 6 \mathbf { B } - 2 ^ { 1 2 } \mathbf { B } } \\ & { \mathbf { K } 8 - 8 1 9 2 \mathbf { B } - 2 ^ { 2 1 } \mathbf { B } } \\ & { + 8 6 \mathbf { K } 8 - 1 6 2 9 \mathbf { B } + 8 - 2 ^ { 1 4 } \mathbf { B } } \\ & { 3 2 \times \mathbf { K } 8 - 3 2 . 7 6 \mathbf { B } - 2 ^ { 1 6 } \mathbf { B } } \\ & { + 4 8 \mathbf { B } - 6 5 . 3 5 8 \mathbf { B } - 2 ^ { 1 4 } \mathbf { B } } \\ & { 1 2 8 \mathbf { K } 8 - 1 3 1 . 0 7 2 \mathbf { B } = 2 ^ { 1 7 } \mathbf { B } } \\ & { 2 5 6 \mathbf { K } 8 - 2 2 . 1 4 4 8 - 2 ^ { 1 5 } \mathbf { B } } \\ & { 3 2 \times \mathbf { B } - 3 2 . 4 2 8 \mathbf { B } - 2 ^ { 1 8 } \mathbf { B } } \\ & { + 5 1 2 \times \mathbf { B } - 3 2 . 4 2 8 \mathbf { B } - 2 ^ { 1 8 } \mathbf { B } } \\ & { 1 . 0 2 4 8 \mathbf { K } - 1 . 0 4 8 5 7 6 \mathbf { B } - 2 ^ { 2 8 } \mathbf { B } \times 1 0 ^ { 6 } \mathbf { B } } \end{array} }
$$

请注意最左侧一排的数字也以2的幂的顺序逐步递增。

我们把1024个字节简化成为了1KB，相同的逻辑，我们把1024 KB统称为1兆字节（megabyte，希腊文中的mega意味着宏大)，兆字节通常缩写为MB。下面这个例子表示了兆字节为单位的存储容量翻倍的过程。

$$
\begin{array} { r l } & { \mathrm { 1 ~ } \mathbf { M } \mathbf { B } = 1 , 0 4 8 , 5 7 6 \mathrm { ~ B } = 2 ^ { 2 0 } \mathrm { ~ B } \approx 1 0 ^ { 6 } \mathrm { ~ B } } \\ & { 2 \mathrm { ~ } \mathbf { M } \mathbf { B } = 2 , 0 9 7 , 1 5 2 \mathrm { ~ B } = 2 ^ { 2 1 } \mathrm { ~ B } } \\ & { 4 \mathrm { ~ } \mathbf { M } \mathbf { B } = 4 , 1 9 4 , 3 0 4 \mathrm { ~ B } = 2 ^ { 2 2 } \mathrm { ~ B } } \end{array}
$$

编码—隐匿在计算机软硬件背后的语言

210

## PDF_PHYSICAL_PAGE_INDEX=227 | PRINTED_PAGE=211

$$
{ \mathbf { 8 } } \ { \mathbf { M B } } = { \mathbf { 8 } } , 3 { \mathbf { 8 } } { \mathbf { 8 } } , 6 0 { \mathbf { 8 } } \ { \mathbf { B } } = 2 ^ { 2 3 } \ { \mathbf { B } }
$$

$$
1 6 \ \mathbf { M } \mathbf { B } = 1 6 , 7 7 7 , 2 1 6 \ \mathbf { B } = 2 ^ { 2 4 } \ \mathbf { B }
$$

$$
\mathbf { 3 2 \ M B } = \mathbf { 3 3 } , \mathbf { 5 5 4 } , \mathbf { 4 3 2 } \ \mathbf { B } = 2 ^ { 2 5 } \ \mathbf { B }
$$

$$
6 4 ~ { \mathrm { M B } } = 6 7 , 1 0 8 , 8 6 4 ~ { \mathrm { B } } = 2 ^ { 2 6 } ~ { \mathrm { B } }
$$

$$
1 2 8 \ \mathrm { M B } = 1 3 4 , 2 1 7 , 7 2 8 \ \mathrm { B } = 2 ^ { 2 7 } \ \mathrm { B }
$$

$$
2 5 6 ~ { \mathrm { M B } } = 2 6 8 , 4 3 5 , 4 5 6 ~ { \mathrm { B } } = 2 ^ { 2 8 } ~ { \mathrm { B } }
$$

$$
5 1 2 ~ { \mathrm { M B } } = 5 3 6 , 8 7 0 , 9 1 2 ~ { \mathrm { B } } = 2 ^ { 2 9 } ~ { \mathrm { B } }
$$

$$
1 , 0 2 4 ~ { \bf M } { \bf B } = 1 , 0 7 3 , 7 4 1 , 8 2 4 ~ { \bf B } = 2 ^ { 3 0 } ~ { \bf R } \approx 1 0 ^ { 9 } ~ { \bf B }
$$

希腊文中的giga意味着巨大，1024 MB也就被顺其自然地称为1吉（gigabyte）字节，缩写为GB。

同理，1太字节（terabyte，teras希腊语意思为巨人）表示 $2 ^ { 4 0 }$ 个字节（约为 $1 0 ^ { 1 2 } \ .$ 也就是1,099,511,627,776个字节，太字节的缩写为TB。

1KB近似为1000个字节，1MB近似为100万个字节，1GB近似为10亿个字节，1TB近似为1万亿个字节。

比 TB 还高数量级平时一般很少使用，比如 $2 ^ { 5 0 }$ 个字节表示为1批字节（petabyte）,计算出来就是1,125,899,906,842,624个字节，约等于一千万亿，即 $1 0 ^ { 1 5 }$ 字节。1安字节(exabyte)代表 $2 ^ { 6 0 }$ 个字节，也就是1,152,921,504,606,846,976个字节，约为100万的3次方，即1018。

我们来补充一些生活中的基本常识。在写本书时（1999年），家用电脑的随机存储器的容量一般为32MB、64MB或128MB（为了避免混淆，这里的任何描述都不涉及硬盘驱动器的任何内容，范围仅仅限定为RAM)，通过计算可以得到它们的存储大小分别为33,554,432个字节、67,108,864个字节和134,217,728个字节。

简洁明了是我们人类交流方式的一大特色。比如，家中电脑内存大小如果为65,536字节，我们会说“我的是64K（这句话很可能是在1980年听到的)”；家中电脑内存大小如果为33,554,432字节，我们会说“我的是32M”。有少数电脑配备了1,073,741,824字节的内存，他们或许会说“我的可是上了G的（有时这句话的英文表述会让人误以为你在谈论音乐———I've got a gig )”。

10 存储器组织

211

## PDF_PHYSICAL_PAGE_INDEX=228 | PRINTED_PAGE=212

有时人们可能会用到千比特或兆比特(注意是比特而不是字节)，这只是极少数情况。当我们讨论涉及存储器的相关问题时，通常使用的是字节数而非比特（需要的时候可以通过把字节数乘以8将其转换成比特)。有一种情况下我们会经常用到千比特和兆比特，那就是在描述在线路中流动的数据时，很多句子中经常会出现千比特每秒（kbps）或兆比特每秒（mbps）这些用语。例如，一台56K的调制解调器指的是其数据处理速度为56千比特每秒，而不是56千字节每秒。

既然我们已经学会如何构造任意大小的RAM阵列，接下来继续对这个问题深究下去。假设现在已经构造好了一个容量为65,536字节的存储器组织，如下图所示。

为什么选择大小为 64 KB的 RAM阵列？而非 32 KB 或128 KB？因为 65,536 是一个约整数，转换为幂的形式就是216，这个RAM阵列需要配备16位的寻址端。换句话说，该地址恰好可以用2个字节表示。将地址范围转化为十六进制就是0000h\~FFFFh。

我前面也提到过，64KB的内存是1980年的个人电脑的主流配置，但它的确不是用电报继电器组成的。我们可以用继电器来组成一块内存吗？我也相信你不想这么做。在我们先前的讨论中，存储每个比特需要9个继电器，推算一下64K×8的RAM阵列就需要至少500万个继电器！

如果用一种控制面板来辅助我们管理对这块 64KB 存储器的操作包括写数据和读数据，一切将会直观明了。在这款控制面板上，有16个开关用于控制地址位，还有8个开关用来控制要输入的8比特数据。写操作端也用一个开关来表示，8个灯泡用来显示8位数据，这个控制面板如下图所示。

初始状态下所有的开关均置为 $0 _ { \circ }$ 其中右下角有一个标识为控制端（takeover）的开关，这个开关的作用是确定由控制面板还是由外部所连接的其他电路来控制存储器。如果其他电路连接到与控制面板相连的存储器，这时控制端置0（如图所示)，此时存储器由其他电路系统接管，控制面板上的其他开关将不起任何作用；当控制端置1时，控制

编码隐匿在计算机软硬件背后的语言

212

## PDF_PHYSICAL_PAGE_INDEX=229 | PRINTED_PAGE=213

面板将重新获得对存储器的控制能力。

这种功能可以用一些2-1选择器来实现。仔细数一下会发现，我们需要25个2-1选择器其中包括16个地址输入端、8个数据输入端，以及1个写操作端。电路如下图所示。

当控制端开关断开时，RAM阵列的地址端、数据输入和写操作端的数据全部来源于外部信号，也就是在2-1选择器的左上角的输入信号；当控制端开关闭合，RAM阵列的地址端、数据输入端和写操作端的数据来源于控制面板开关发出的信号。但最终RAM阵列的输出信号都会传输到8个灯泡上或其他可能的地方。

16 存储器组织

213

下一段：[继续读取](https://workshop.closeclaw.top/api/ai/read/38270854-596f-4a26-8183-db8c968c6020.md?start=230&limit=10)
