Skip to content

LV001-计算机的基本组成 ​

在点亮第一块单片机开发板之前,我们先回答一个更根本的问题:计算机是由什么组成的?它为什么能自动工作?

单片机(MCU)本质上就是一台被压缩到一颗芯片里的计算机。这一篇里的每个概念——运算器、控制器、存储器、指令、寄存器——后面都会在 STM32 里一一对应地再次出现。把这一篇读懂,后面所有章节其实都是在"对号入座"。

本篇的阅读主线是一条因果链:计算机只会简单运算 → 复杂问题必须先被人翻译成简单运算 → 让机器自动执行这些运算需要"存储程序" → 存储程序要求机器具备五大部件 → 五大部件靠"取指-分析-执行"的循环运转起来。

一、 计算机是如何解题的 ​

1. 计算机只会简单运算 ​

一个容易被忽略的事实:计算机再强大,硬件层面也只会做加减乘除四则运算和逻辑判断(与、或、非、比较大小)。那它怎么算 sin x、开根号、算微分方程?答案是人工先把问题"降维"成计算机能算的形式。例如 sin x 可以用泰勒级数展开成一系列加减乘除:

sin⁡x=x−x33!+x55!−x77!+⋯

再比如开平方,可以用迭代公式反复逼近:

xn+1=12(xn+axn)

只要迭代次数够多,结果就会无限接近真实值。"把复杂运算化归为有限次简单运算",这是用计算机解题的第一个前提。

2. 解决问题分两大步骤 ​

用计算机解决一个实际问题,工作分成性质完全不同的两段:

(1)上机前的准备——人的工作,又分三步:

  • 建立数学模型:把实际问题抽象成数学方程。比如预测人口增长,抽象成微分方程;统计销量趋势,抽象成回归模型;
  • 确定计算方法:把数学方程化成只含四则运算的近似计算公式,比如上面 sin x 的级数展开。同一个问题往往有多种算法,精度、速度、内存占用各不相同,这一步直接影响程序质量;
  • 编制解题程序:把运算步骤翻译成一条条机器指令。程序就是"适合机器运算的全部步骤",机器只会执行程序,不会理解问题。

(2)上机运行——机器的工作:程序和数据送入计算机,机器自动逐条执行指令,最后输出结果,全程不需要人干预。

【注意】

"自动"两个字是这一篇的关键词。1946 年之前,"计算机"是一群拿着计算尺和手摇计算机的人;ENIAC 诞生后,计算速度提高了上千倍,但编排计算步骤仍然靠人手工插线、扳开关——换一道题就要重新接线几个小时。计算机组成原理要回答的核心问题之一,就是:机器是怎么从"人拉一步走一步"变成"自己一步步走下去"的。

二、 冯·诺依曼体系结构 ​

1. 从 ENIAC 的痛点说起 ​

世界上第一台通用电子数字计算机 ENIAC(1946 年,美国宾夕法尼亚大学)每秒能做 5000 次加法,但它的"程序"存在接线板里:想换个题目计算,要几个工程师手动改线好几天。计算快,换题慢,机器大部分时间在等人接线。

1945 年,参与 ENIAC 后续项目 EDVAC 的数学家冯·诺依曼(von Neumann)发表了著名的《EDVAC 报告书的第一份草案》,指出了问题的根源和解法:指令也应该像数据一样,存放在存储器里,让机器自己按地址去取。

2. 存储程序思想 ​

这一思想的核心只有一句话:

将程序(指令)和数据一样,预先存放在存储器中,机器按照指令在存储器中的地址自动地、依次地取出并执行。

以此概念为基础的各类计算机统称为冯·诺依曼机。从你手里的 STM32 到顶级的服务器 CPU,八十年来几乎所有计算机都延续着这个思想。它带来的直接后果是:换一道题不再需要重新接线,只需要把新的程序写进存储器——"编程"取代了"接线"。

3. 五大部件 ​

要落实"存储程序",机器必须具备五类功能部件,各司其职:

部件职能通俗理解生活中的对应
运算器完成算术运算和逻辑运算,中间结果暂存在运算器内干活的计算器芯片
存储器存放数据和程序仓库书架
控制器指挥程序和数据的输入、运行以及结果处理指挥的大脑
输入设备把人熟悉的信息形式转换为机器能识别的形式进货口键盘、鼠标
输出设备把运算结果转换为人熟悉的信息形式出货口显示器、打印机

五大部件在控制器的统一指挥下有条不紊地自动工作。注意控制器是"指挥"而非"动手":它只发命令,真正算数的是运算器,真正存取的是存储器。

4. 冯·诺依曼机的特点 ​

把上面的内容归纳成教科书式的五条:

(1)指令和数据以同等地位存放于存储器内,并可按地址寻访;

(2)指令和数据均用二进制数表示——二进制只有 0 和 1 两种状态,用高低电平就能稳定区分,这是电子实现的天然选择;

(3)指令由操作码和地址码组成,操作码表示操作的性质(做什么),地址码表示操作数在存储器中的位置(对谁做);

(4)指令在存储器内按顺序存放,通常按顺序执行,特定条件下可根据运算结果或设定条件改变执行顺序(这就是跳转,if/else/循环的硬件基础);

(5)早期机器以运算器为中心,输入输出设备与存储器之间的数据传送都要经过运算器,运算器成了繁忙的"必经之路";现代计算机已改进为以存储器为中心,I/O 数据不再绕道运算器,系统吞吐量大幅提升。

5. 另一种流派:哈佛结构 ​

冯·诺依曼的"程序和数据混放一炉"并不是存储程序的唯一实现方案。与之相对的是哈佛结构(Harvard Architecture),名字来自哈佛大学 1944 年的 Mark I 计算机——它把指令存在打孔纸带上、数据存在机械计数器里,从一开始就是物理分开的。现代哈佛结构的定义是:指令存储器与数据存储器分开,各有独立的地址总线与数据总线,取指与数据访问可以并行进行。两种结构的对比如下:

冯·诺依曼结构与哈佛结构对比

  • 冯·诺依曼:一套存储器、一套总线,简单且内存分配灵活(程序数据各占多少运行时决定),代价是取指与取数共用通道、只能分时排队(著名的"冯·诺依曼瓶颈"),而且程序与数据同区,代码可能被当作数据误改;
  • 哈佛:两套存储器、两套总线,取指与取数并行互不抢占,指令区还可以做硬件只读保护,代价是结构与成本翻倍,程序区/数据区的大小出厂就固定、不能灵活调配。

【注意】

这里先记住一个结论:后面要学的单片机(包括 STM32)普遍采用哈佛结构的一种改进形态,而 PC 采用的是冯·诺依曼式的统一内存。两者各自为什么这样选,与存储介质(FLASH/SRAM)和工作方式(XIP/按需装载)强相关,等到讲完单片机的组成与架构后再展开分析(见 LV013-单片机的通用架构)。

三、 五大部件逐一拆解 ​

1. 运算器 ​

运算器的核心是算术逻辑单元 ALU(Arithmetic Logic Unit),配合若干寄存器完成运算。以一个最简模型为例,参与运算的寄存器有三类:

  • ACC(Accumulator,累加器):存放被操作数或运算结果,是使用最频繁的寄存器;
  • MQ(Multiplier-Quotient Register,乘商寄存器):乘法时存放乘数、除法时存放商,配合 ACC 完成乘除;
  • X:存放另一个操作数(加数、被乘数、除数等)。

例如计算 a + b:a 先放入 ACC,b 放入 X,ALU 做加法后结果回到 ACC。运算器内部这些寄存器的存在,正是后面 LV016-寄存器与硬件控制 要讲的"寄存器"概念的第一批实例。

2. 控制器 ​

控制器的任务是"解释并指挥",它靠两个关键寄存器和一套控制逻辑工作:

  • PC(Program Counter,程序计数器):存放下一条要执行的指令的地址,CPU 每取完一条指令,PC 自动加 1(按指令字长增加),指向下一条——程序的"自动推进"就是 PC 在驱动;
  • IR(Instruction Register,指令寄存器):存放当前正在执行的指令本身,供控制器分析;
  • CU(Control Unit,控制单元):对 IR 中的指令译码,产生一系列微操作命令,分发给各部件。

控制器本身不产生数据,它生产的是"命令":什么时候读存储器、什么时候让 ALU 做加法、什么时候把结果写回,全部由 CU 协调。

3. 存储器 ​

主存储器(简称主存或内存)是整个体系的枢纽,可以形象地理解成一栋"宿舍楼":

  • 存储体像一栋大楼,由许多存储单元(房间)组成;
  • 每个存储单元里有许多存储元件(床位),每个元件寄存一位二进制代码 0 或 1;
  • 一个存储单元存放的一串二进制代码称为一个存储字,其位数称为存储字长(相当于床位数);
  • 每个存储单元有一个编号,称为存储单元的地址(房间号)。

【注意】

地址和内容是两回事:3 号房间住着谁,与"3"本身无关。访问存储器时给出的是地址,取到的是该地址里的内容。这个区分贯穿整个计算机体系,指针、间接寻址等概念都建立在它之上。

为了实现按地址访问,主存必须配两个寄存器作"桥梁":

  • MAR(Memory Address Register,存储器地址寄存器):存放将被访问的存储单元的地址。MAR 的位数决定可寻址的单元个数——MAR 为 16 位时,可寻址 216=65536 个单元,记作 64K(1K = 1024 = 210);
  • MDR(Memory Data Register,存储器数据寄存器):存放从存储体某单元取出或准备存入的代码,其位数等于存储字长。

读存储器的完整过程:地址送 MAR → 存储器按 MAR 选中单元 → 该单元内容被读出送 MDR。写过程则相反:地址送 MAR、数据送 MDR → 存储器把 MDR 内容写进 MAR 指向的单元。如今 MAR 和 MDR 都已集成在 CPU 芯片内部。

容量单位从小到大依次为 K、M、G、T,均为 1024 进制(210、220、230、240)。存储容量 = 存储单元个数 × 存储字长,例如 MAR 16 位、MDR 32 位,容量就是 216×32 位 = 256 KB。

4. 输入设备与输出设备 ​

输入设备把信息形式转换的方向是"人 → 机器":键盘把按键变成字符编码,鼠标把位移变成坐标数据,摄像头把图像变成像素数组。输出设备方向相反:"机器 → 人":显示器把字符编码变成字形,打印机把数据变成纸上的墨迹,音箱把数字信号变成声音。

有的设备兼有两职:触摸屏既是输入也是输出;磁盘驱动器保存文件时是输出、读取文件时是输入。因此两者统称I/O 设备(Input/Output Equipment)。

5. 从五大部件到三大部件 ​

运算器和控制器在逻辑关系和电路结构上联系十分紧密——控制器译码出的命令大部分是发给运算器的。大规模集成电路工艺出现后,这两大部件往往集成在同一块芯片上,合称中央处理器(Central Processing Unit,CPU)。于是现代计算机的硬件常按三大部分描述:

  • CPU = 运算器 + 控制器;
  • 主存储器:存放程序和数据;
  • I/O 设备:输入设备 + 输出设备。

其中 CPU 与主存储器合称主机,I/O 设备又称外部设备(外设)。这个"三位一体"的视角,正是看懂现代计算机组成框图(见下图)的钥匙:

现代计算机组成框图

图中实线是数据流:程序与数据从输入设备进入主存,结果从主存送往输出设备,主存与运算器之间双向交换数据;虚线是控制流:控制器向其余四个部件发号施令。这个"以存储器为中心"的结构,正是教材上经典的现代计算机组成框图。

四、 计算机如何自动执行程序 ​

1. 指令的组成 ​

指令(Instruction)是机器语言的语句,告诉计算机"做什么、对谁做",其格式固定为两段:

  • 操作码 OP:指明操作性质,如取数、存数、加、乘、打印、停机;
  • 地址码 A:指明操作数所在的存储单元地址(或结果存放地址、下一条指令地址等)。

下面是一台教学用假想机器的指令系统节选:

操作码操作性质具体内容
000001取数将地址码指示的存储单元中的操作数取到运算器的累加器 ACC 中
000010存数将 ACC 中的数存至地址码指示的存储单元中
000011加将 ACC 中的数与地址码指示的存储单元中的数相加,结果存于 ACC 中
000100乘将 ACC 中的数与地址码指示的存储单元中的数相乘,结果存于 ACC 中
000101打印将地址码指示的存储单元中的操作数打印输出
000110停机停止运行

2. 一个完整的例子:计算 ax2+bx+c ​

用上面的指令系统计算 ax2+bx+c。直接照公式算需要 4 次乘法、2 次加法;先改写成 (ax+b)x+c,只需 2 次乘法、2 次加法——先优化算法,再写程序,这个顺序在任何时代都成立。

设指令和数据依次存放在主存 0~12 号单元,程序清单如下:

主存地址操作码地址码注释
00000010000001000取数 x 至 ACC
10001000000001001乘 a 得 ax,存于 ACC 中
20000110000001010加 b 得 ax+b,存于 ACC 中
30001000000001000乘 x 得 (ax+b)x,存于 ACC 中
40000110000001011加 c 得 ax²+bx+c,存于 ACC 中
50000100000001100存数,将结果存入主存单元
60001010000001100打印结果
7000110停机
8x原始数据
9a原始数据
10b原始数据
11c原始数据
12存放结果

这张表值得仔细看,有三个细节埋着后面的伏笔:

(1)指令和数据混放在同一个存储器里:0~7 号是指令,8~12 号是数据,它们都是一串二进制代码,在存储器中没有本质区别——是"当指令取"还是"当数据取",完全取决于 PC 指向哪里。这正是存储程序思想的直观体现,也是"程序即数据"的起点;

(2)运算结果回 ACC,再由存数指令写回主存:数据不会凭空消失,总是在寄存器和存储器之间搬运——后面学 STM32 时,C 变量在寄存器和 SRAM 之间的流动与此一模一样;

(3)最后一条是停机指令:程序必须自己知道在哪里结束。

3. 取指令、分析指令、执行指令 ​

现在回答本篇开头的问题:机器怎么"自己一步步走下去"?控制器的工作是一个永不停止的三步循环:

(1)取指(Fetch):把 PC 的内容送 MAR,命令存储器读出该单元的指令,指令经 MDR 送入控制器的 IR;

(2)分析(Decode):CU 对 IR 中的指令译码——操作码指出"做什么",地址码指出"操作数在哪个存储单元";

(3)执行(Execute):根据译码结果发出微操作命令:取操作数、命令 ALU 运算、存结果或输出。

一条指令执行完,PC 早已自动指向下一条指令的地址,于是又回到第(1)步……计算机的工作过程,就是周而复始地取指令、分析指令、执行指令。只要存储器里有程序、时钟在跳,这个循环就一直转下去,直到遇到停机指令或断电。

后面学 STM32 的中断时会看到:中断、异常本质上是"强行把 PC 改成另一个地址",让循环临时转到别处执行,处理完再跳回来——万变不离这个取指循环。

五、 衡量计算机性能的指标 ​

有了部件和结构的语言,就可以量化地谈论一台计算机的"规格":

  • 机器字长:CPU 一次能处理数据的位数,通常与 CPU 内部寄存器的位数有关。说"8 位机""32 位机"指的就是它——后面要学的 STM32F103 是 32 位机;
  • 存储容量:存储单元个数 × 存储字长,常以 MAR 位数 × MDR 位数刻画,如 216×32 位。习惯上也用字节数表述,如 64 KB;
  • 主频:CPU 内部时钟的频率,决定 CPU 动作的节拍。主频越高,一次取指-执行循环的每个步骤完成得越快,如 STM32F103 的 72 MHz;
  • 运算速度:与主频相关但更贴近真实体验,常用指标有三个:
    • MIPS(Million Instructions Per Second):每秒执行的百万条指令数;
    • CPI(Cycle Per Instruction):执行一条指令所需的平均时钟周期数——同一主频下 CPI 越小越快;
    • FLOPS(Floating Point Operations Per Second):每秒浮点运算次数,衡量科学计算能力。

【注意】

主频和性能不能简单画等号:一条复杂指令可能要几十个时钟周期(CPI 大),一条简单指令可能只要 1 个。这就是为什么早年 1 GHz 的 Pentium III 和后来 1 GHz 的移动 CPU 性能天差地别——架构和 CPI 不同。

六、 从计算机到单片机 ​

把本篇的整套概念压缩到一颗芯片上,对照关系如下:

本篇的通用概念单片机里的对应
ALU + CU + 寄存器组内核(如 ARM Cortex-M3)
主存储器(存程序)FLASH(掉电不丢)
主存储器(存数据)SRAM(掉电丢失)
输入输出设备片上外设:GPIO、UART、定时器、ADC……
取指-分析-执行循环内核每秒数千万次的日常

这张表就是下一篇的主角——单片机的预告。带着"五大部件去了哪里"这个问题,进入 LV004-什么是单片机。

七、 参考资料 ​


本文档由 markdowncli 技能辅助生成