序章 0:开讲之前,先把这四件事讲明白
为什么要有这一章? 教材一开头就讲”冯·诺依曼”、“寄存器”、“二进制”、“时钟周期”——这些词不解释你也”知道”,但其实你只是听过,并不真的懂。这一章用 4 个故事把这 4 件事讲透,看完你的脑子里会有真东西,而不是 4 个空名词。
0.1 第一个问题:在冯·诺依曼之前,人是怎么”编程”的?
你听过”冯·诺依曼结构”这个词无数次,但它伟大在哪?要回答这个,得先看看它之前的机器有多惨。
故事:ENIAC 的痛
🛟 几个底层电学名词一次讲清(之后正文不再解释):
- 门电路 (Gate) = 用几个晶体管搭成的最小逻辑零件,只做一件事。常见三种:非门 (NOT) 输入 0 出 1、输入 1 出 0;与门 (AND) 两个输入都为 1 才出 1;或门 (OR) 任一输入为 1 就出 1。整个 CPU 的所有运算电路最终都是这三种门的组合。
- 组合电路 = 由门电路堆出来的电路,输入一变输出立即变(不用时钟)。ALU 就是典型——你换两个数它一拍内吐出结果。
- 时序电路 = 在组合电路基础上加了”记忆元件”(触发器/锁存器),需要时钟驱动才会更新。寄存器、PC、IR 都是时序电路。
- 上升沿 / 下降沿 = 时钟方波从低跳到高的那一瞬间叫上升沿(↑);从高跳到低叫下降沿(↓)。“边沿触发”的元件只在那一瞬间动一下,其余时间高电平再长它也不理。
后面看到任何”门""组合""时序""沿”,回这里查就行。
1946 年,美国造出了世界上第一台电子计算机 ENIAC(埃尼亚克),重 30 吨,占地 170 平方米,每秒能算 5000 次加法——在当时是宇宙级速度。
但它有一个致命问题:怎么”编程”?
答案是:手动接线。
ENIAC 的"编程"现场:
┌──────────────────────────────────────────────────────┐
│ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ │
│ □ □ □ □ ●═══● □ □ ●═════════● □ □ □ □ □ □ □ □ □ │
│ □ □ ●═════════════● □ □ □ □ □ ●═══● □ □ □ □ □ □ │ ← 6000个开关
│ □ ●═● □ □ □ □ □ □ □ □ □ □ □ □ □ □ ●═════● □ □ □ │ ← 几千根插线
│ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ │
└──────────────────────────────────────────────────────┘
↑ ↑
6 位女程序员花 3 天才能把"算个弹道"的程序"接"出来
是的,没有”代码”这种东西。要让 ENIAC 算别的题,得6 个女工程师在机器前花 2–3 天,把上千根插线拔下来重插一遍、6000 个开关调一遍。算完一道题,要换下一道?再拔再插再调。
🌱 大白话:ENIAC 的”程序”不是”写”的,是接出来的。整台机器的硬件结构就是那个程序——换程序 = 重新搭机器。
冯·诺依曼的”灵光一现”
1945 年,数学家 冯·诺依曼(John von Neumann)看到 ENIAC 后写了一份报告,提出一个今天看来”理所当然”、当时却惊天动地的想法:
既然机器能处理”数字”(输入的数据),为什么不能把”程序本身”也当成数字、提前存进机器里?让机器自己一条条读出来执行?
这就是**“存储程序”**——四个字,整个现代计算机产业的奠基石。
ENIAC 时代: 冯·诺依曼之后:
程序 = 机器的物理接线 程序 = 一堆数字,和数据混在一起存内存
换程序 = 重新接 3 天 换程序 = 把另一堆数字读进内存(几毫秒)
机器 = 只能干一种活 机器 = 同一台硬件干无限多种活
→ 不可商用、不能复制 → 通用计算机的诞生
这件事的伟大之处是:硬件第一次从”具体的功能”中解放出来——硬件只负责”按规则读数字、做数字、写数字”,至于这堆数字代表什么活,全由用户决定。这才有了今天你的手机能同时是电话、相机、地图、游戏机——它的硬件就一份,“程序”换来换去。
🔑 记住这个对比:以后听到”存储程序”四个字,脑子里要立刻浮现”ENIAC 的女工拔了 3 天插线” vs “现代电脑切换程序只需一瞬间”。这才是它的分量。
🌱 大白话:冯·诺依曼说:“别再把菜谱焊在厨房里了,把菜谱写在纸上和食材一起放冰箱,让厨师自己去翻就行。” 这一句话,让计算机从”专用工具”变成了”通用工具”。
0.2 第二个问题:为什么计算机偏偏用”二进制”,不用十进制?
你肯定听过”计算机用 0 和 1”。但为什么?人类天生用十进制(因为有 10 根手指头),机器不能也用十进制吗?
答案藏在硬件最底层的物理事实里。
🛟 如果你连”电压""电流”都没把握,先看这段;如果熟,可跳过: 想象一根水管,水管里流的”水”= 电流;推水流动的”水压”= 电压。 一个开关装在水管上:“开”=水通了=电流流过;“关”=水堵住=没电流。 数字电路里所有元件本质都是这种”被某个信号控制开/关”的小阀门——只是用电而不是水。 “高电压代表 1”是人类定的一个约定——也可以反过来用低电压代表 1(叫”负逻辑”),结果完全等价,只是约定不同。
物理事实:晶体管只有两个稳定状态
计算机的所有硬件,最终都由数以亿计的 晶体管 (Transistor) 组成。一个晶体管的本质,是一个由电压控制的”开关”:
一个晶体管的工作方式:
┌─────────────────────┐
│ 控制极 (Gate) │ ← 给它一个电压
│ │ │
│ ▼ │
│ ┌─────┐ │
│ │ 开/关 │ ←─电流──│ ← 决定电流通不通
│ └─────┘ │
└─────────────────────┘
高电压 (~5V) → 开 → 电流通 → 我们规定它代表 "1"
低电压 (~0V) → 关 → 电流断 → 我们规定它代表 "0"
为什么不能搞三个状态、四个状态来表示十进制?
理论上可以,物理上极难做稳定。比如要表示 0/1/2/3 四个数字,得分别用 0V / 1.7V / 3.3V / 5V 四档电压。问题来了:
- 电路里永远有噪声(其他元件干扰、温度波动),实测电压可能是 1.5V、3.0V、3.5V,到底算哪档?
- 制造误差:100 万个晶体管不可能完全一致,有的 1.7V 有的 1.6V,判错就出大事。
- 速度:要分辨四档比分辨两档慢得多。
而只有两档时:低于 1V 一律算 0、高于 4V 一律算 1,中间留宽宽的”缓冲带”,怎么干扰都不会判错。
两态判别(极宽容): 四态判别(极敏感):
5V─┐ ←─── 全算 1 5V─┐ ← 算 3
│ (高电平稳定区) 4V─┤ ← 算 3 还是 2?模糊
4V─┤ 3V─┤ ← 算 2
│ 2V─┤ ← 算 2 还是 1?模糊
│ ←── 这一大段是缓冲 1V─┤ ← 算 1
│ 带,怎么晃都不会 0V─┘ ← 算 0
1V─┤ 误判
│ (低电平稳定区)
0V─┘ ←─── 全算 0
🌱 大白话:二进制不是”人选的”,是电子元件天生只擅长两个状态——亮/灭、通/断、磁极 N/S。逼它做”亮一点点”和”亮很多”的区分,它判不准。所以整个数字计算机帝国,都建在”晶体管只能做开关”这一条物理事实上。
那”二进制”具体怎么表示数字?
约定俗成:用一串 0/1 按”逢二进一”组合,就能表示任意大小的数字。
十进制 5 = 二进制 101 (1×4 + 0×2 + 1×1 = 5)
十进制 13 = 二进制 1101 (1×8 + 1×4 + 0×2 + 1×1 = 13)
十进制 255 = 二进制 11111111 (8 个 1,最大 8 位无符号数)
所以以后看到”32 位整数”,脑子里浮现的应该是:32 个晶体管排成一排,每个要么导通要么截止,组合起来就是一个数。
🔑 从此你就懂了:第 2 章讲”补码/IEEE754”,其实都是在解决”怎么用 0/1 这两个字符,把负数、小数、超大超小的数也表示清楚”的问题。所有数据表示方法,都是给”只会 0/1 的硬件”擦屁股。
0.3 第三个问题:CPU 里的”寄存器”到底是什么?为什么不直接用内存?
你后面会无数次看到 R1、R2、PC(Program Counter,程序计数器——记着”下一条指令在内存哪个位置”)、IR(Instruction Register,指令寄存器——存着”当前正在执行的那条指令”)这些”寄存器”。问题是——寄存器到底是什么?它和内存有什么区别?
速度的真相:CPU 等内存等到怀疑人生
现代电脑里几个东西的访问速度(用"等多久"对比):
寄存器 (Register) 约 0.3 ns ← CPU 内部,"伸手就拿到"
L1 Cache 约 1 ns ← 还在 CPU 内
L2 Cache 约 3 ns
L3 Cache 约 10 ns
内存 (Main Memory) 约 100 ns ← 出 CPU 走总线,远多了
硬盘 (SSD,固态硬盘) 约 100,000 ns
机械硬盘 约 10,000,000 ns
如果把 CPU 取一次寄存器的时间想象成”伸手拿桌上的笔”(1 秒),那么:
- 取一次内存 ≈ 走出办公室、坐电梯下楼、走到对面写字楼(约 5 分钟)
- 取一次硬盘 ≈ 从北京飞到纽约(约 4 天)
CPU 跑得太快,内存比它慢 100 倍。如果每算一步都要去内存搬数据,CPU 大部分时间都在等——这就是著名的”存储墙 (Memory Wall)“问题。
解决方案:在 CPU 里放一些”超快的小本本”
CPU 内部专门用触发器电路(触发器 = 用 4–6 个晶体管搭出的”小记忆元件”,给它输入端送一个 0 或 1,它就记住,断了输入也不忘——直到下次被改写。把它想成”用电子门栓锁住一个 0 或 1”)做了几十到几百个”小本本”,每个能存一个数字(通常 32 或 64 位)——这就是寄存器。
后面看到
ALU(算术逻辑单元,Arithmetic Logic Unit)就是 CPU 里做加减与或非的那个核心电路块——你给它两个输入数和一个”该做什么”的指令,它就在一拍内给你结果。寄存器把数据喂给 ALU、再接住 ALU 的输出,整个 CPU 算数的故事就这么循环。
CPU 内部 (放大看):
┌──────────────────────── CPU 芯片 ────────────────────────┐
│ │
│ ALU (运算单元) │
│ ↑↓ │
│ ┌─ 寄存器组 ─┐ ← 32 个小本本 │
│ │ R0 ━━━━━━│ 每个本能写一个 32 位数 │
│ │ R1 ━━━━━━│ CPU 0.3 ns 就能读/写一次 │
│ │ R2 ━━━━━━│ │
│ │ ... │ │
│ │ R31 ━━━━━━│ │
│ └────────────┘ │
│ │
└────────────────────────────────────────────────────────────┘
↕ 通过"总线"这条线
┌────────────────────────────────────────────────────────────┐
│ 内存 (DRAM,Dynamic Random-Access Memory,动态随机存取存储器,几个 GB) ← 100 ns 才能读一次 │
└────────────────────────────────────────────────────────────┘
寄存器的”工作原则”:
- 数量少(几十个)但飞快(0.3 ns)。
- CPU 算数时,操作数必须先搬进寄存器——ALU 只能从寄存器读、往寄存器写,不能直接对内存算。
- 比如 a+b,真实的步骤是:① 把 a 从内存搬到 R1;② 把 b 从内存搬到 R2;③ ALU 算 R1+R2,结果放 R3;④ 把 R3 写回内存。两次搬进来、一次算、一次搬回去,总共 4 步,这就是 RISC(Reduced Instruction Set Computer,精简指令集计算机——指令少而整齐,每条指令固定几拍完成)的”Load/Store 架构”的真相。
🌱 大白话:内存是”楼下仓库”,便宜大碗但远;寄存器是”工作台上的笔筒”,只能插几支笔,但伸手就有。你在桌上算账,总得先把账本从仓库搬到桌上才能算——这就是”先 LOAD 进寄存器再 ADD”的物理本质。
🔑 后面看 PC、IR、AR(Address Register,地址寄存器——存着”要去访问的内存门牌号”)、DR(Data Register,数据寄存器——临时存着”刚从内存取来的数据”)、PSW(Program Status Word,程序状态字——记着”刚才的运算有没有溢出、进位”等标志位)这些”专用寄存器”,本质都一样:它们就是 CPU 内部留出来专门记某件事的”小本本”——PC 记”下条指令在内存哪个门牌号”、IR 记”我手里这条指令是啥”、PSW 记”刚才算出来溢出了没”。
0.4 第四个问题:CPU 为什么能”自动一步步走”?谁在背后打节拍?
冯·诺依曼说”机器按地址自动取指令一条条执行”——可机器凭什么自动?它怎么知道”现在该取下一条了”?
答案:靠时钟 (Clock)——CPU 的”心跳”。
物理事实:CPU 板上有个晶振,它每秒振动几亿到几十亿次
打开你电脑的 CPU,里面(其实主板上)有一块叫 晶振 (Crystal Oscillator) 的小晶体。给它通电,它会因为压电效应以极其精确的频率振动,产生一个方波信号:
🛟 “压电效应”是啥? 一句话:某些晶体(如石英)一通电就会以极其稳定的频率自己抖动——人类不用管为啥,用就完了:它能输出一根脉冲规律的方波线,整台电脑就靠这根线”打节拍”。你手腕上的石英表里也有同一种东西。
时钟信号 (Clock Signal) 长这样:
高电平 ─┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──
│ │ │ │ │ │ │ │ │ │
低电平 └──┘ └──┘ └──┘ └──┘ └──┘
└──┬──┘
│
└── 一个"时钟周期" (Clock Cycle / 节拍)
也就是教材里说的 "T"
你的电脑主频 3 GHz = 每秒 3,000,000,000 个这样的方波
→ 一个时钟周期 = 1/3 ns ≈ 0.33 ns
时钟驱动是怎么让 CPU “动”起来的?
CPU 里每一个寄存器、每一个触发器都有一根”时钟输入线”,连到这个方波信号上。这些电路有一个共同规则:
只在时钟方波从低跳到高的那一瞬间(上升沿),才”锁住”新的输入;其他时刻保持不变。
一个寄存器对时钟的响应:
时钟 ───┐ ┌────┐ ┌────┐ ┌──
│ │ │ │ │ │
└──┘ └──┘ └──┘
↑ ↑ ↑
这一瞬间,寄存器"咔嚓"锁住此时输入端的值
其他时间,输入怎么变它都不理
输入端 ──XXX──╳──YYY──╳──ZZZ────
寄存器内容 XXX YYY ZZZ ← 每个节拍换一次
于是,整台 CPU 就像一支跟着鼓点行进的方阵:每听到一声鼓(时钟上升沿),所有部件同时进入下一个状态。这一拍:“PC 把指令地址送到内存”;下一拍:“内存把指令送回 IR”;再下一拍:“译码器看清这是 ADD 指令”……
🌱 大白话:CPU 不是”自动想运转”,是有一个外置的电子节拍器一直在敲鼓,CPU 的每个零件都被规定”听到鼓声才能动一下”,于是整台机器就这么一拍一拍按部就班地走。关掉时钟,CPU 立刻”僵在原地”——它不是死了,只是没人喊”换”了。
由此引出”周期”的三层包含关系
教材里那个让人头大的”指令周期 ⊇ 机器周期 ⊇ 时钟周期”,本质就是:
时钟周期 = 鼓的一拍(最小单位) ≈ 0.3 ns
↓ 几拍打包
机器周期 = 完成一个"明确小动作"所需的几拍
(比如"从内存取一次数据"通常要 3–5 拍)
↓ 几个小动作组成
指令周期 = 完成一条机器指令的全部时间
(取指 + 译码 + 执行 + 写回,整体可能要 10–20 拍)
🔑 后面学第 5 章 “CPU 指令周期” 时,记住这个:不是 CPU 自己”决定”花几拍,是设计者把指令的执行过程拆成了一连串”听到鼓声就动一下”的微小动作,鼓点固定,动作累加,时间就出来了。
⭐ 序章 0 总结:建好这四块地基,再去看课本
| # | 你建立的认知 | 它解决了什么后面会迷糊的问题 |
|---|---|---|
| 0.1 | 存储程序之前要”接线”——所以冯·诺依曼的伟大是”让程序变成数据” | 第 1 章为什么把”存储程序”列为冯氏三大思想之首 |
| 0.2 | 二进制是被晶体管的物理特性逼出来的、不是人选的 | 第 2 章为什么要费那么大劲搞补码/浮点——都是用 0/1 凑出别的数 |
| 0.3 | 寄存器是 CPU 里的”小本本”,比内存快 100 倍 | 第 4、5 章为什么算什么都要”先 LOAD 进寄存器”——内存太慢 |
| 0.4 | CPU 靠时钟方波”被动地”一拍一拍走 | 第 5 章为什么有”时钟周期/机器周期/指令周期”嵌套 |
🎯 从此你看后面任何概念,都可以问自己:“这个概念是在解决什么问题?是为了对付硬件的什么限制?” ——只要能答上这个问题,你就真的懂了,否则就是死记硬背。
🧪 费曼检验区(合上笔记,用自己的话说)
规则:合上笔记,试着说给完全不懂的人听。卡壳了就说明没真懂,回头重读。
📌 老师划重点 (序章内容不直接出题,但以下概念是后续所有章节的基础)
📊 教材核心考点
- 用自己的话解释:二进制为什么用补码?不用补码行不行?
- “时钟周期”和”机器周期”有什么关系?一个机器周期包含几个时钟周期?
- PC(程序计数器)的作用是什么?CPU 怎么知道”下一条指令在哪”?
- 寄存器、Cache、内存、硬盘——它们速度和容量的排序关系是什么?为什么要分这么多层?
📝 章节小测
先想好答案再展开核对。这几道帮你确认”四块地基”是否真的搭稳了。
【题 1 · 判断】 “冯·诺依曼机中,程序和数据都以二进制形式存储在同一个存储器中。” 对还是错?
【题 2 · 判断】 “计算机采用二进制是因为二进制运算规则比十进制简单。” 这个说法完整吗?
【题 3 · 简答】 CPU 内部的寄存器和主存(内存)都能存数据,为什么 CPU 算数时非要先把数据搬进寄存器?
参考答案(点击展开)
题 1:对。这正是”存储程序”思想的核心——指令和数据都用二进制编码、混在同一个存储器里,CPU 按地址自动取出执行。
题 2:不完整。运算规则简单只是次要原因。根本原因是晶体管只有导通/截止两个稳定状态——物理特性决定了二进制是最可靠的表示方式(两态判别有宽容的噪声容限,多态判别极易误判)。
题 3:因为寄存器比内存快约 100 倍(~0.3ns vs ~100ns)。ALU 只能从寄存器读操作数、往寄存器写结果——如果每步都去内存取数,CPU 大部分时间都在等(存储墙问题)。所以 RISC 架构要求”先 LOAD 进寄存器,算完再 STORE 回内存”。