← 返回知识卡片总目录

DS1号 · 自学教材系列 | 计算机软硬件

第 7 章 冯·诺依曼结构与五大部件

前面六章,我们一块砖一块砖地搭出了开关、逻辑门、加法器、记忆。现在到了「盖房子」的时刻:把这些零件按一张蓝图组装起来,就是一台完整的计算机。这张蓝图,就是 70 多年前一个天才提出的「冯·诺依曼结构」——直到今天,你手里的每一台电脑都还在用它。

🎯 本章学习目标

  1. 记住计算机的五大部件:运算器、控制器、存储器、输入、输出。
  2. 理解「存储程序」思想为什么是革命性的。
  3. 理解数据流与控制流的区别,以及总线的作用。
  4. 能把前面学的零件(加法器、寄存器、触发器)对应到五大部件上。

7.1五大部件:一台计算机的蓝图

1945 年,约翰·冯·诺依曼在一份报告草案中,给出了通用计算机的完整设计。他把计算机分成五个部分:

冯·诺依曼结构五大部件
部件英文职责对应我们学过的零件
运算器ALU做算术、逻辑运算加法器、逻辑门
控制器Control Unit指挥各部分按顺序工作译码器、时序电路
存储器Memory存放程序和数据寄存器、内存单元
输入设备Input把外界信息送进来键盘、鼠标等
输出设备Output把结果送出去屏幕、打印机等

📖 人物:冯·诺依曼(John von Neumann) 冯·诺依曼是 20 世纪罕见的天才:数学家、物理学家、计算机科学家、博弈论创始人,还参与了曼哈顿计划。1945 年他起草的《关于 EDVAC 的报告初稿》,首次系统描述了「存储程序」计算机的结构。这份报告影响如此深远,以至于后人把这套结构以他的名字命名。

这五个部件中,运算器和控制器合在一起,就是今天说的 CPU(中央处理器);存储器就是内存;加上输入输出设备,就构成了一台完整的计算机。

冯·诺依曼结构总览 输入设备、输出设备、存储器、CPU(含运算器和控制器)之间的连接关系。 输入设备 键盘、鼠标… 输出设备 屏幕、打印机… 存储器 程序 + 数据 CPU 运算器 + 控制器 总线
图 7-1五大部件通过总线互联:数据在输入→存储→运算→输出之间流动,控制信号由 CPU 发出。

为什么恰好是「五」个部件?这个划分其实深藏功力,值得逐个推敲。存储器必须独立——程序和数据都要有地方放;运算器必须独立——「算」是核心动作;控制器必须独立——多步骤的先后顺序需要指挥。而输入输出为什么也单独成类,不和存储器合并(毕竟数据都要「进出」)?因为它们面对的是两个世界:存储器交换的是 0/1 数字信号,I/O 设备交换的却是按键、光、声这些物理量——中间隔着模数/数模转换,隔着不同的速度等级(键盘几毫秒一个键,CPU 一纳秒一拍),也隔着完全不同的工程问题。把「对内记账」和「对外打交道」分开成类,是抽象上的清醒。

再把前六章的零件对号入座,你会发现自己已经攒齐了全部砖瓦:运算器就是第 5 章的加法器/逻辑门阵列(配上第 5 章的 C、V 标志);控制器内部是第 5 章的译码器(翻译指令编码)加上第 6 章的时序电路(按拍推进);存储器的顶层概念是第 6 章的寄存器排成阵(具体物理实现第 9 章讲);寄存器堆是 CPU 的工作台。还没学的只剩两块:输入输出设备的物理原理(第 14 章),以及把这些部件「串成一台会自己干活的机器」的完整循环——那正是本章后半场的主题。

📐 例题 1 五大部件职责判断五连

以下五个工作场景,请指出主要由哪个部件负责:(a)把角度传感器送来的电压转成数字量送进主机;(b)计算两组导航参数之和并判断有无溢出;(c)记住「程序该执行第几条指令」;(d)把算好的姿态数据变成屏幕上的字符;(e)按指令内容发出「让存储器执行读」的命令。

思路 抓住各部件的职责关键词:输入=物理量→0/1;运算器=算与逻辑;控制器=发号施令、决定顺序;存储器=存内容;输出=0/1→物理量。容易混的是「记指令序号」和「发命令」——一个偏「存」(虽在 CPU 内),一个偏「指挥」。

解 (a)物理量→数字量,是输入设备(含其模数转换)的活。
(b)「算」且「判断溢出」,是运算器(ALU+标志位)的活。
(c)「记」指令序号——存的是内容(PC 寄存器的值),属于存储性质的寄存器(CPU 内的存储细胞;程序计数器本身是控制器用来推进流程的关键寄存器)。
(d)0/1→字符光点,是输出设备的活。
(e)「发出命令」,是控制器的活。

答:输入、运算器、(CPU 内的)寄存器/存储职能、输出设备、控制器。 ⚠ 易错点:(c)最容易答成控制器——PC「被控制器使用」不等于「PC 本身是指挥者」;它存的是数据(一个地址值),本质是存储职能,只是位置在 CPU 内。

航空工程师读这节应当格外亲切:机载电子设备的外场可更换单元(LRU)就是按功能切块的——信号处理单元里能找到运算器,接口单元里全是输入输出电路,电源模块独立成块。冯·诺依曼的五分法之所以历久弥新,正因为它切在「职责的自然接缝」上:按功能分块、按接口互联,这一思想从电路板一直贯通到整个系统的架构。

还要澄清一个高频误区:CPU ≠ 运算器。运算器只是 CPU 的「一半」,另一半是控制器;此外 CPU 里还包着一批寄存器(第 6 章的主角)。把 CPU 等同于 ALU,就像把一支施工队等同于夯机——夯机确实在干活,但「今天先打哪块地基」是队长的调度。分清「干活的」与「调度的」,是本章的关键素养。

7.2存储程序:革命性的思想

冯·诺依曼结构最核心、最革命的一点,不是「有五个部件」,而是 存储程序(stored program)思想。

在冯·诺依曼之前,计算机是「死」的:要让一台机器算不同的问题,得重新插拔电线、改动硬件,换一次任务就像重新造一台机器。冯·诺依曼的洞见是:

核心思想:程序也是数据 把「程序」(要执行的指令序列)当作普通数据,存进存储器里,和它要处理的数据放在同一个仓库中。这样,换任务只需换存储器里的内容,硬件完全不用动。计算机从此从「专用机器」变成了「通用机器」——同一台硬件,靠换程序就能干任何事。

这个思想的美妙在于一个看似矛盾的点:指令和数据,在存储器里长得一模一样,都是 0 和 1。怎么区分哪段是指令、哪段是数据?答案是:看它们「在什么时候、被谁读取」——控制器在「取指」阶段读到的,就当作指令;运算器在「取数」阶段读到的,就当作数据。同一段 0/1,身份由上下文决定(这个伏笔第 11 章会展开)。

🧠 一句话记忆 存储程序 = 把程序当数据存起来,换程序不必换硬件。这是计算机「通用」的秘密。

「换任务要重新接线」离今天的体验太远,值得用一台真实的机器把它讲实。ENIAC(1946 年,世界上第一台通用电子计算机)正是「插线板时代」的巅峰之作:一万八千多只电子管堆出的运算能力惊人,但它「认任务不认人」——每换一个问题,工程师们要手动设置成百上千个开关、重插成百上千根线缆,动辄数小时甚至数天。这意味着机器算一个新问题,光「布线改配置」的时间就可能超过真正的计算时间。而在存储程序结构下,同一个动作变成「把新程序写进存储器」——毫秒到秒级的事。一个数量级接一个数量级的差距,就是「革命性」三个字的分量。硬件从「为每个任务定制」中彻底解放出来,从此只需把硬件做得更快,而「让机器干什么」交给软件去表达。

由此还催生了一个全新职业与产业:程序(软件)从此是可以独立制造、独立交付的产品。硬件厂不再需要为每个应用重排电路,而是一批批造通用机器;写程序的人在上面定义机器的行为。今天你升级一个应用商店里的软件、下载一个新固件包,本质上都是「换存储器里的内容,硬件一字不动」——这正是 1945 年那份报告播下的种子。在航空领域,机载设备的功能升级走的是同一条路:加改装常常不是换板子,而是加载新版机载软件——硬件不变、程序重灌,功能焕然一新;相应的适航审定关注点,也从「电路改没改」延伸到了「软件版本是否受控」。

顺带把「换存储器里的内容」这个说法落到实处:程序平时躺在磁盘这类「仓库级的存储」里,开机或启动应用时,由一个加载过程把它复制进内存(RAM),控制器才开始逐条取指执行;而最先执行的「把加载器自己跑起来」的那小段程序,则由更底层的引导(bootstrap)过程完成——先有一小段固化在只读存储里的代码负责「把更大的程序搬进内存」,接力棒一层层交下去,直到整个操作系统站起来。你每天按下电源键后的那几秒黑屏等待,正是这场接力赛的现场。第 12 章讲操作系统时,这条加载链会正式展开。

「程序也是数据」还有一条不那么温馨的推论:既然指令和普通数据躺在同一仓库、长得一模一样,那么被当作数据写入的内容,也可能在某一天被当作指令执行——一个被引导去「读入并执行」的恶意数据文件,就是病毒能够存在的根本原因。存储程序给了机器通用性,也给了「程序被程序改写」以可能。这既是动态加载、自我修改程序等技术的源头,也是安全防护必须面对的底层现实。

📐 例题 2 「存储程序」判断四连

判断下列系统是否体现「存储程序」思想,并说明理由:(a)某计算器,按功能键直接做四则运算;(b)某通用计算机,从磁盘加载不同软件做打字或算账;(c)某数控机床,从存储卡读入加工程序加工不同零件;(d)某老式电子密码锁,密码错误三次就锁死,功能出厂固化不能改。

思路 判据只有一条:「换功能」是否只需换存储器里的内容,而硬件不动。

解 (a)功能固定在按键电路上,算「专用电路」,不是存储程序。(b)同一硬件、换程序换任务,是存储程序的标准形态。(c)加工程序存在存储卡里,换零件只换卡里的内容——存储程序思想在工业控制上的直接应用。(d)「三次锁死」的逻辑焊死在电路里,改功能要动硬件,不是存储程序。

答:(b)(c)是;(a)(d)不是。 ⚠ 易错点:别把「有芯片、有存储」就当存储程序——关键是流程(程序)本身存在可更换的存储器里,而不是电路结构固定、只存几个参数。

最后补一个高阶辨析:哈佛结构(Harvard architecture)——指令与数据分开存放、分开走线,甚至各配一套存储器与总线。它和冯·诺依曼结构是一对镜像:冯·诺依曼是「一仓一总线,指令数据混装」;哈佛是「两仓两总线,指令数据分家」。各自的理由都成立:混装灵活(程序可被当作数据读写,通用性强,主存统一管理简单);分家高效(取指与取数并行进行,互不排队,且程序区天然不易被改坏)。有趣的是,现代高性能 CPU 实际上是两者的混合:内存层面指令数据混住(冯·诺依曼),但 CPU 内部紧贴运算单元的第一级高速缓存却分成「指令缓存(L1I)」与「数据缓存(L1D)」两套(哈佛)——用哈佛的并行度,保冯·诺依曼的通用性。而许多单片机(MCU)则从头到尾都是纯哈佛:程序放 Flash、数据放 RAM,物理隔离、各走各线。考试若问「哈佛结构与冯·诺依曼结构的本质区别」,标准答案就一句:指令与数据是分开存储还是共用存储。

7.3运算器与控制器:CPU 的两半

运算器(ALU):只会加减的「计算狂」

运算器,又称 ALU(Arithmetic Logic Unit,算术逻辑单元),负责真正的「算」。它的核心就是我们第 5 章搭的加法器,外加一些逻辑门。它能做的,本质就是加减、移位、与或非、比较这些基本操作——所有复杂运算,最终都被拆成这些。

「所有复杂运算最终都被拆成基本操作」这句轻描淡写的话,值得展开看一眼。乘法是移位加累加:二进制乘法里,乘数的每一位要么贡献一次「被乘数左移若干位」,要么不贡献,控制器让 ALU 反复做加法即可;除法是移位减比较的试凑过程;浮点运算则是「拆指数尾数、对阶、移位、加减、再规格化」的组合拳。你在第 5 章为补码加法器配的进位标志 C 与溢出标志 V,在 ALU 里同样是现役装备:减法借位看 C,有符号溢出看 V——比较两数大小(先做减法再看标志)也靠它们。ALU 是「只会基本动作的运动员」,但任何复杂舞步都能拆成基本动作的组合,这正是它以少胜多的底气。

控制器(Control Unit):发号施令的「指挥」

控制器自己不计算,它只做一件事:按照程序的指令,指挥其他部件一步步行动。它读取下一条指令、翻译这条指令是什么意思、然后发出控制信号,让 ALU 去加、让存储器去读、让寄存器去存。

拆开控制器的内囊,你会发现里面全是老朋友:一个译码器(第 5 章)负责把指令的 0/1 编码翻译成「哪条线该亮」;一套时序电路(第 6 章)负责按节拍推进「取指→译码→执行」;一个程序计数器 PC(本质是个计数寄存器)记住「下一条指令在存储器的哪个位置」,每执行完一条就自动加一。取指、译码、执行三拍循环往复,就是计算机运转的心跳——第 6 章的时钟每敲一下,这个循环就向前走一步。控制器就是「用译码器和时序电路实现的自动指挥家」,你学过的零件在这里集合完毕。

分工的本质 运算器管「怎么算」,控制器管「算哪一步」。一个出力气,一个出主意。二者合称 CPU——计算机的大脑。

🧠 一句话记忆 ALU 动手,控制器动口;一个算,一个指挥。

📐 例题 3 「把 3+5 存起来」——四步指令的旅程

某简化计算机中,内存地址 100 存着数 3,地址 101 存着数 5,程序从地址 0 开始依次存放三条指令:① LOAD R1, [100](把地址 100 的数装入寄存器 R1);② ADD R1, [101](把地址 101 的数与 R1 相加,结果放回 R1);③ STORE [102], R1(把 R1 存入地址 102)。请逐步列出每条指令执行时「哪些部件在动、数据怎么流」,并写出执行结束时 PC、R1、地址 102 的值。

思路 对每条指令都走一遍「取指→译码→执行」三拍:取指时控制器经总线从存储器取指令、PC 同时指向下一条;译码时控制器翻译出该让谁动;执行时数据按指令要求流动。逐条记账即可。

解
指令① LOAD:取指——控制器从地址 0 取指令,PC 由 0 变 1;译码——「装数」;执行——存储器把地址 100 的 3 经总线送入寄存器 R1。此时 R1=3。
指令② ADD:取指——PC 由 1 变 2;译码——「取数并相加」;执行——存储器送出地址 101 的 5,运算器算 3+5=8,结果写回 R1。此时 R1=8。
指令③ STORE:取指——PC 由 2 变 3;译码——「存数」;执行——R1 的 8 经总线写入存储器地址 102。
程序执行完毕:PC=3(指向下一条即将到来的指令),R1=8,地址 102 的内容=8。

答:PC=3,R1=8,[102]=8。全程存储器动了三次「读」一次「写」,运算器只算了一次 3+5,输入输出设备一次都没参与——不是每条指令都需要五大部件全员出动;控制器则从头到尾每拍都在发信号。 ⚠ 易错点:ADD 执行时别把「3」写成从内存重读——它已在 R1 里躺着;以及 PC 在「取指」的同时就完成加一,不是整条指令结束后才加。

把控制器与时钟接上,还能算一笔时间账:一条指令要走完「取指→译码→执行」,通常消耗若干个时钟周期(简单指令两三拍,复杂指令十几拍)。用第 6 章的换算工具立即能估出速度量级——若时钟 2 GHz(一拍 0.5 ns)且平均每条指令 4 拍,则每条指令约 2 ns,一秒钟约执行五亿条指令。这就是「主频」与「实际性能」之间的换算链:主频决定一拍多快,指令平均拍数(体系结构决定)决定一条指令要几拍,两者相乘才是每秒指令数。第 8 章 CPU 流水线要优化的,正是「让多条指令的各拍重叠进行」,把这条换算链再压短。

再看一个易混点:ALU 自己不保存结果。它像食堂的打饭窗口,算完一勺立刻递出去——递给寄存器、递给存储器,窗口台上不留菜。所以「先算 a+b 存起来,下一步再算 (a+b)+c」必须有个寄存器接住中间结果 a+b。记住这个分工:算完必有人接,接的人永远是存储性质的单元(寄存器或内存)。这也解释了为什么 CPU 里要塞那么多个寄存器——它们是 ALU 的餐盘架。

7.4存储器:程序与数据的共同仓库

存储器存放两样东西:正在运行的程序,和程序正在处理的数据。它像一张巨大的、编了号的「格子表」,每个格子(存储单元)有一个唯一的编号叫 地址(address),里面存着一小段 0/1。

记忆的最重要特性是随机访问:你可以直接读任意编号的格子,不用从头一个个翻。就像查字典,直接翻到第 500 页,而不是从第 1 页数起。这种「按地址直接存取」的存储器,叫 RAM(Random Access Memory,随机存取存储器)。

存储器 = 带地址的格子 一排存储单元,每个有唯一地址,存着一段数据。 地址 内容(0/1) 0000 0011 0101 0001 1010 0001 0010 1111 0000 按地址直接读写,无需从头翻 —— 这就是「随机访问」
图 7-2存储器 = 一串编了号的格子。地址是格子的编号,内容是一段 0/1。

把「地址」和「内容」这对概念再拧紧一圈,它们是一栋楼里的门牌号与住户的关系:门牌号(地址)标在墙上,住户(内容)是可以换的;把 501 室的家具全搬空,501 这个门牌号依然存在。所以「擦掉某个格子的内容」「往某个格子写新数据」都不会改变格子的编号——地址由芯片的连线决定,内容才是每条指令真正读写的东西。另一个常被忽略的推论:CPU 访问存储器时,地址与内容是分两趟传递的——先把「我要第 500 号」放到地址总线上,再把第 500 号的内容搬上数据总线。理解了这一点,下一节「地址总线」「数据总线」为什么是两类线,就不言自明了。

顺着「地址总线要多少根线」往下想,还能得到本章最重要的公式之一:每根地址线是一个 bit,n 根地址线一共能编码多少个不同地址?答案是 2 的 n 次方(就是第 2 章「n 个 bit 有 2ⁿ 种组合」的直接应用)。

存储单元总数 = 2地址线根数 → 总容量 = 2n × 每单元位数

📐 例题 4 地址线根数与寻址容量

(a)某 CPU 有 16 根地址线,每单元 1 字节,最多能寻址多大容量?(b)20 根地址线呢?(c)32 根呢?(d)反过来:要直接寻址 4 GB(每个地址对应 1 字节),至少需要多少根地址线?

思路 n 根地址线 → 2n 个不同地址 → 2n 个存储单元;每单元 1 字节,2n 字节再除以 1024 换算成 KB/MB/GB(1024=2¹⁰,每次连除 10 次方就跳一级单位)。

解 (a)2¹⁶ = 65536 单元 = 65536 字节,65536÷1024 = 64 KB。
(b)2²⁰ = 1048576 字节 = 1024 KB = 1 MB。
(c)2³² = 4294967296 字节 = 4 × 1024 × 1024 × 1024 字节 = 4 GB。
(d)反向:4 GB = 2³² 字节,需 2n ≥ 2³²,故 n = 32 根。

用一小段 Python 当场验算(也当作这一换算的通用工具):

addr_bits = 16              # 地址线根数
cells = 2 ** addr_bits      # 可寻址的存储单元数
print(cells, cells // 1024, "KB")   # → 65536 64 KB

units = ["字节", "KB", "MB", "GB"]
for n in (16, 20, 32):
    print(n, "根地址线 ->", 2 ** n // 1024 ** (n // 10), units[n // 10])

程序第一行的输出:65536 64 KB——与手算一致。三档容量对照:16→64 KB、20→1 MB、32→4 GB。

答:64 KB;1 MB;4 GB;32 根。 ⚠ 易错点:① 用 1000 而不是 1024 换算,会得到「62.5 KB」之类的错误答案——内存容量按惯例用二进制 1024 进制;② 忘记容量还与「每单元位数」有关——若每单元 4 字节,16 根地址线的容量还要乘 4。

📐 例题 5 地址范围换算(十六进制)

某存储芯片容量为 8 KB,起始地址为 0x0000。(a)它的地址范围是 0x0000 到多少?(b)若另一块 1 KB 的芯片紧挨着它从 8 KB 边界开始排,其起始地址是多少?

思路 容量 8 KB = 8192 = 0x2000 个地址,起始为 0,则末地址 = 0 + 8192 − 1 = 0x1FFF(地址从 0 起编,故要减 1——「0 也占一个号」是初学者最容易漏的一步)。第二块芯片的起始地址 = 第一块的容量,即 0x2000 = 8192。

解 (a)8 KB = 8 × 1024 = 8192 个单元;0x0000 + 8192 − 1 = 8191 = 0x1FFF。范围:0x0000 ~ 0x1FFF。
(b)起始地址 = 0x2000;1 KB = 1024 = 0x400,所以它覆盖 0x2000 ~ 0x23FF。

答:0x0000~0x1FFF;起始 0x2000,1 KB=0x400。 ⚠ 易错点:末地址不是 0x2000 而是 0x1FFF——「从 0 开始编号」意味着第 8192 个格子的编号是 8191。十六进制换算口诀:4096=0x1000、1024=0x400、255=0xFF。

还剩一个悬着的词要交代:「每单元 1 字节」是什么意思?一台机器的存储单元按惯例以字节(byte,8 个 bit)为最小编号单位——地址 0、地址 1、地址 2……每个门牌号背后是 8 个格子,而不是单个 bit。为什么不按 bit 编号?因为 8 个 bit 恰好装下一个字符编码或一条小指令的片段,按 bit 编号会让地址数字暴涨 3 倍、无谓加宽地址总线。由此也自然衔接另一个高频词——字长:CPU 一次能并行处理的 bit 数(比如 64 位)。「64 位 CPU」说的是它的寄存器和运算通路一次吞吐 64 个 bit(8 个字节),而不是说内存地址有多长——地址线根数与字长是两个独立参数,只是碰巧在很多年代的产品里都是 64。

这个「2 的 n 次方」还有一个著名的现实回响:早年 32 位计算机配 4 GB 内存时,系统往往认不全、只显示 3 GB 多——因为 2³² = 4 GB 的地址总量里,还得留出一部分给显存、BIOS、各类接口的寄存器映射,留给内存的地址不够 4 GB 了。这是「地址是编号资源、资源有限就要规划」的生动一课,也是后来 64 位 CPU(寻址能力指数级暴涨)迅速普及的直接动力。

第 9 章我们会深入内存的物理原理(它到底怎么「存」住 0 和 1)。这里你只需要建立这张「带地址的格子表」的直觉。

7.5输入与输出设备

计算机再聪明,也得和人、和世界打交道。输入设备把现实世界的信息(按键、声音、图像)转换成 0/1 送进来;输出设备把 0/1 还原成人能感知的光、声、字。

输入/输出设备举例
类型设备转换方向
输入键盘、鼠标、麦克风、摄像头、触摸屏现实信息 → 电信号/0和1
输出屏幕、扬声器、打印机0和1 → 光/声/墨迹

把这张表往深处看一层:输入输出设备干的其实是同一件事——翻译。输入设备是「物理世界→二进制世界」的翻译官(麦克风把气压波翻译成 0/1,摄像头把光强翻译成 0/1);输出设备是「二进制世界→物理世界」的翻译官(声卡把 0/1 翻译成气压波,显卡把 0/1 翻译成光点)。真正的计算只发生在二进制世界里,物理世界负责「收发」。

但翻译这份差事并不轻松,难点全在「两个世界节奏差太多」:CPU 一拍只要零点几纳秒(第 6 章:3.5 GHz 的时钟一拍约 0.29 ns),而你敲一个键要几十毫秒——速度差了七八个数量级。硬让 CPU 盯着键盘等,等于让短跑世界冠军蹲在门口等一封三天后才寄到的信。所以每个 I/O 设备身后都站着一个接口控制器:它用第 6 章的触发器把慢信号「接住存稳」,等攒够了再通过总线一次性交给 CPU;两边各按各的节奏,控制器负责「对暗号、存中转」。这套缓冲思想第 14 章展开。

📐 例题 6 触摸屏:输入还是输出?

一块智能座舱里的触摸屏,属于输入设备还是输出设备?某键盘带背光,又属于哪类?

思路 别按「设备」整体分类,按信息方向拆开看:玻璃下面那层感应你手指位置的电路,是把「物理按压位置」翻译成坐标数据——输入方向;同一块屏发光显示画面,是把像素数据翻译成光——输出方向。

解 触摸屏 = 触摸感应层(输入)+ 显示层(输出),一体两面:点选图标时它是输入设备,刷新画面时它是输出设备,两个身份同时成立、互不冲突。带背光的键盘同理:按键电路是输入,背光是输出——只是后者太不起眼,日常就直接归入输入设备了。

答:都是「输入输出一体」的复合设备。分类看信息流向,不看外壳。 ⚠ 易错点:把 I/O 当互斥标签、非此即彼——判断题「触摸屏是输入设备」(√)与「触摸屏是输出设备」(√)可以同时为真。

飞机上这套翻译逻辑尤其直观:大气数据计算机把皮托管的压力(物理量)翻译成高度、空速数据(输入侧),驾驶舱显示器再把高度、空速数据翻译成屏幕上的数字与刻度(输出侧)——两端都是翻译,中间的运算才是计算。

输入输出是计算机的「感官」和「手脚」。它们的具体原理(键盘怎么扫描按键、屏幕怎么发光)会在第 14 章专门讲。

7.6数据流、控制流与总线

五大部件要协同工作,需要两样东西「流动」起来:

承载这些流动的物理通道,叫 总线(bus)。总线通常分三类:

三类总线
总线英文传什么
数据总线Data bus实际的数据(双向)
地址总线Address bus要访问的内存地址(CPU 发出)
控制总线Control bus读写、时序等控制信号

📖 名词溯源:bus 为什么叫「总线」 bus 来自拉丁语 omnibus(「给所有人的」),本义是「公共马车」,谁都能上、谁都能下。引申到电子工程里,就是一条大家共用的通道——多个部件共享同一组线路传输信号。中文译作「总线」,「总」即「汇总、公用」之意。

核心思想 数据流搬运「数据」,控制流搬运「号令」,两者都跑在总线上。理解这两股流,是理解「计算机如何运转」的关键视角。

「公共马车」这个比喻还藏着它最大的软肋:一条线同一时刻只能传一单货。总线是共享通道,两个部件同时想说话就得排队——由总线仲裁电路(本质是第 5 章的优先编码器思想)决定谁先上。这就像小区只有一部电梯:住户多了,高峰期就得等。计算机史上的经典困境「冯·诺依曼瓶颈」正源于此——指令和数据共用一条总线,取指和取数不能同时进行,CPU 再快也被总线卡着脖子。前面说的「CPU 内部分指令缓存与数据缓存」的哈佛式改造,就是把这两股最急的车流分流到两条快道上,正是缓解瓶颈的工程手段。

一条指令的旅程:五大部件间的数据流与控制流 实线箭头表示数据流(输入到存储、存储到 CPU、CPU 到存储、存储到输出),虚线表示控制器发出的控制流。 CPU 控制器 运算器 存储器 输入设备 输出设备 ① ② ③ ④ 控制流 数据流
图 7-3一条指令的旅程(实线为数据流,虚线为控制流):① 输入设备把原始数据存入存储器;② 控制器取指、运算器取数;③ 运算结果写回存储器;④ 结果送往输出设备。控制器全程用虚线的控制流调度一切。

📐 例题 7 用「数据流/控制流」双视角重走例题 3 的程序

仍用例题 3 的程序(LOAD R1,[100];ADD R1,[101];STORE [102],R1),对照图 7-3:把整个执行过程拆成「数据流动作」和「控制流动作」两份清单,并回答——三条指令中,「数据流从存储器流向 ALU」发生了几次?「控制流」一共发生了多少次发出?

思路 数据流认「内容在动」:指令代码、操作数、结果都是内容;控制流认「号令在动」:译码后发出的每一个「读/写/算」信号。注意取指阶段的指令代码虽然是指令,但在总线上它同样是「被搬运的内容」,算数据流动作。

解 数据流清单:取指①②③各一次(指令从存储器到控制器);LOAD 执行一次(数 3 从存储器到 R1);ADD 执行两次(数 5 从存储器到 ALU、结果 8 从 ALU 回 R1);STORE 执行一次(8 从 R1 到存储器)——共 7 次。控制流清单:每条指令译码后各发出一组信号——「存储器读」「寄存器写」「ALU 加」等,共 3 组(每组含若干根信号线同时生效)。
「存储器→ALU 方向的数据流」只在 ADD 执行时发生 1 次(数 5 那一趟;3 是直接进寄存器 R1,没经过 ALU)。控制流的发出在每条指令的译码拍都有,3 条指令共 3 次。

答:数据流 7 次、控制流 3 组;存储器→ALU 仅 1 次。 ⚠ 易错点:① 别把「取指」当控制流——指令本身是内容,在总线上的搬运是数据流;「译码后发出的信号」才是控制流;② ADD 的 3 在 R1 里,不经总线、不经 ALU,别多算。

三类总线的分工 CPU 与存储器、输入输出设备之间,数据总线、地址总线、控制总线三条通道的连接与方向。 CPU 发起访存的源头 存储器 格子表 输入输出设备 速度慢,需接口缓冲 数据总线(双向) 货:指令、操作数、结果 地址总线(单向) 门牌号:要访问哪个格子(虚线示意读回校验等少量例外) 控制总线 号令:读/写、就绪、中断(双向各司其职)
图 7-4三类总线各司其职:数据总线运「货」,地址总线发「门牌号」,控制总线传「号令」。一次访存要先经地址总线点名、控制总线下令,数据总线才装货。

总线的能力有一个可以直接算出来的硬指标——带宽(每秒能搬多少字节)。它由两个因素相乘决定:一次能搬多少(数据总线的位宽),一秒能搬几次(时钟频率,理想情况下每个时钟周期传送一次)。

总线带宽 = 数据总线位宽(字节) × 每秒传送次数 → 带宽(字节/秒) = 位宽/8 × 频率

📐 例题 8 总线带宽计算

某系统数据总线宽度为 64 位,总线时钟 100 MHz,每个时钟周期完成一次数据传送。(a)理论带宽是多少 MB/s?(b)若时钟提到 200 MHz,带宽变为多少?(c)反过来,要达到 3.2 GB/s,在位宽不变的前提下频率需要多少?

思路 先统一单位:64 位 = 8 字节;100 MHz = 10⁸ 次/秒。带宽 = 8 字节 × 10⁸ 次/秒 = 8×10⁸ 字节/秒。总线带宽按工程惯例用十进制(1 MB/s = 10⁶ 字节/秒),与内存容量的 1024 进制区分开。

解 (a)8 × 10⁸ 字节/秒 = 800 MB/s。
(b)频率翻倍、位宽不变,带宽同比例翻倍:8 × 2×10⁸ = 1.6×10⁹ 字节/秒 = 1.6 GB/s。
(c)3.2 GB/s ÷ 8 字节 = 4×10⁸ 次/秒 = 400 MHz。(另一条路:位宽翻到 128 位、频率维持 200 MHz,同样得 3.2 GB/s——提频与加宽是提升带宽的两条平行路径。)

答:800 MB/s;1.6 GB/s;400 MHz。 ⚠ 易错点:① 忘记把「位」换成「字节」(除以 8),会得 6400 MB/s 的离谱答案;② 别用 1024 换算带宽——总线速率按十进制惯例计。

📐 例题 9 这算数据流、控制流,还是地址信息?

下列五个信号/传送,各属于数据流、控制流,还是地址总线上传送的地址信息?(a)键盘扫描码经总线写入存储器;(b)控制器发出的「存储器执行读」信号;(c)加法器的结果 8 经总线写回存储器;(d)PC 中的指令地址放上地址总线;(e)I/O 设备发来的「数据就绪」信号。

思路 三问定属性:内容是「被加工/被搬运的信息」吗(数据流)?是「指挥谁去做什么的号令」吗(控制流)?还是「指明去哪个格子的门牌号」(地址总线的信息,可称地址流——它既不是被加工的数据,也不是号令,而是数据的坐标)?

解 (a)扫描码是被存的信息——数据流。
(b)号令——控制流。
(c)运算结果——数据流。
(d)内容是个地址,但它在总线上只是「指路」,没有被加工——地址信息(跑在地址总线上;PC 本身存的是数据,但此刻它输出的内容被用作地址)。
(e)状态汇报类的号令——控制流(控制总线不只是 CPU 发号,I/O 向 CPU 汇报也走它)。

答:数据流、控制流、数据流、地址信息、控制流。 ⚠ 易错点:地址是最容易被错归到「数据流」的一类——判据不是「内容像不像数字」,而是「它是被加工的货物,还是货物的门牌号」。

三根「水管」里最特别的是地址总线的单向性:门牌号永远由 CPU 发出、存储器只被动接收,反向没有箭头。原因不难想:若存储器也能往地址总线上发号,两个「发号者」就会在同一根线上打架(数字电路里叫总线冲突),读出的地址面目全非。所以「谁有权发地址」被严格规定——普通访存由 CPU 发,DMA(第 14 章的 Direct Memory Access,让 I/O 设备不经 CPU 直取内存)则由仲裁器临时把发号权移交给专用的 DMA 控制器,移交期间 CPU 闭嘴。单向线的纪律换来的是确定性:地址总线上永远只有一个声音。数据总线则相反,谁都可以往里放数据,只要轮流来——这就是它标「双向」的含义:双向指的是方向可变,同一时刻仍只有一个部件在发。

把这节收拢成一句工程直觉:硬件设计者盯住的是三根「水管」各要多粗——数据总线决定一次运多少货(例题 8 的位宽),地址总线决定门牌号能编到多大(例题 4 的 2ⁿ),控制总线决定号令体系够不够用(读写、就绪、中断各有专线)。水管再粗也要排队(仲裁),所以「带宽不够」与「瓶颈分流」是系统设计里永恒的谈判——CPU 厂商一代代把内存控制器搬进 CPU、把缓存一级级加厚,都是在给这根公共马车专线疏堵。

辨析:冯·诺依曼瓶颈 vs 存储墙——两个常被混用的病名 两者都在说「CPU 等数据等得苦」,但病灶完全不同,读性能优化的新闻时先分清再归因。冯·诺依曼瓶颈是结构病:指令与数据共用一套总线与内存端口,取指与取数天然要排队(7.2 节那部「小区电梯」)。存储墙(memory wall)是速度病:CPU 与 DRAM 的速度差一代比一代大——CPU 主频以 GHz 计、一拍不足 1 纳秒,内存一次访问却要几十纳秒,而且几十年间几乎原地踏步。差距有多离谱,算一笔就懂:3 GHz 的 CPU 一拍约 0.33 纳秒,一次约 80 纳秒的访存折合 CPU 白等 80 × 3 = 240 拍。对策因此分两条战线:治结构病靠「分流」——指令缓存与数据缓存分设(思考题 7 的哈佛式改造正是此意)、总线加宽加多;治速度病靠「垫层」与「预取」——用缓存金字塔把常用数据搬到近处,趁 CPU 忙别的活提前把可能要用的数据搬进来。病名分清,药方自然归位:再看到任何一条优化技术,你都能立刻说出它治的是「排队」还是「太远」。

本章小结

  1. 冯·诺依曼结构把计算机分成五部件:运算器、控制器、存储器、输入、输出。
  2. 运算器 + 控制器 = CPU;一个管算,一个管指挥。
  3. 存储程序思想(程序当数据存)让计算机从专用变通用,是革命性的。
  4. 存储器是「带地址的格子表」,随机访问(按地址直接读写)是其关键。
  5. 数据流搬数据、控制流搬号令,二者都跑在总线上。
  6. 存储容量 = 2 的地址线根数次方;地址是门牌号,内容是住户,擦掉内容不改变地址。
  7. 总线带宽 = 位宽 × 频率;数据总线运货、地址总线发门牌号、控制总线传号令。

读完本章,你应该能……

思考题

1. 冯·诺依曼结构五大部件是哪五个?运算器和控制器合称什么?

提示:运算器、控制器、存储器、输入、输出;运算器+控制器=CPU。

2. 为什么「存储程序」让计算机从专用变成通用?

提示:程序当数据存,换任务只换内存内容,硬件不用改。

3. 存储器里指令和数据都是 0/1,怎么区分它们?

提示:看读取时机——取指阶段读到的是指令,取数阶段读到的是数据。

4. 数据总线、地址总线、控制总线各传什么?

提示:数据、内存地址、控制信号。

5. 某 CPU 有 20 根地址线、每单元 1 字节,最多能直接寻址多大内存?

提示:2²⁰ = 1048576 字节 = 1024 KB = 1 MB。注意 20 根线恰好跨过 1024 的倍数界,是早期 PC「1 MB 寻址」的经典数字。

6. 触摸屏属于输入设备还是输出设备?为什么?

提示:都属——感应层把触摸位置翻译成数据(输入),显示层把数据翻译成光(输出)。分类看信息流向,不看外壳。

7. 哈佛结构与冯·诺依曼结构的本质区别是什么?现代高性能 CPU 用的是哪种?

提示:指令与数据是分开存储(哈佛)还是共用存储(冯·诺依曼)。现代 CPU 是混合体:内存层面混存(冯·诺依曼),CPU 内部一级缓存分指令/数据两套(哈佛),取两制之长。

8. 程序计数器 PC 属于五大部件中的哪一个?它物理上住在哪里?为什么不能住在存储器里?

解析:属于控制器——它是 CPU 内部一枚专用寄存器,既不是运算器的零件,更不是存储器里的格子。它必须住在 CPU 里:取指的每一步都要读它,几乎每条指令执行完都要改它,访问频度冠绝全场;若把它放进内存,则「读 PC」本身又变成一次访存——「为了取指令而先去取地址」,取地址又得知道地址在哪儿,无限套娃。控制器把 PC、指令译码电路与控制信号发生电路放在一起,才指挥得动全场:PC 是那根「手指」,手指不能住在手指要指的地方。

9. 某 CPU 主频 3 GHz,一次内存访问约 80 纳秒,这次访存折合 CPU 白等多少拍?这个数字解释了什么现象?

解析:3 GHz 一拍 = 1/3 纳秒 ≈ 0.33 纳秒;80 ÷ 0.33 ≈ 240 拍。一次访存够 CPU 空转两百多个周期——这就是「存储墙」的直观刻度:CPU 再快,喂不上料也是白搭。缓存的全部意义就浓缩在这个数字里:把最常用的数据放进 1 纳秒级的高速存储,让绝大多数访存不必付出 240 拍的代价(第 8、9 章会反复用到这笔账)。