Atri Website

Back

冯诺伊曼架构#

”存储程序”的概念#

存储程序是为了解决早期 ENIAC 机时由人类手动接线来控制计算的问题。

其核心理念:将编译好的程序和初始数据存入计算机的主存储器,由计算机读取在主存中的首地址来执行程序的第一条指令,由此实现自动、连续的取指令并执行的操作。

架构图#

1

即由 Input 设备输入数据,将其传给运算器,由运算器决定存储、输出。

特点#

  1. 由五个部分组成:运算、控制、存储, IO
  2. 指令和数据以相同的形式存储于存储器:都是按照地址访问
  3. 指令和数据都以二进制形式存储(废话)
  4. 指令由 操作码 和 地址码 组成。操作码:加、减等操作
  5. 以运算器为中心

现代计算器架构#

现代计算器在冯架构上改进,为了提高性能,由以运算器为中心改为以存储器为核心

2

输入设备直接访问存储器进行存储。

3

主存与辅存

主存指的是计算机的内存,辅存指的是电脑的固态硬盘、机械硬盘。

辅存存储的是程序和代码,例如手机的 APP;而主存则是程序运行时,才会把程序加载到内存里执行。

计算机的功能部件#

存储器#

4

存储器内部主要部件为 存储体、 MAR 和 MDR。

MAR 为地址寄存器,用于存放 CPU 想要访问的存储地址。MDR 为数据寄存器,用于存放存储体提供给 CPU 的对应地址的数据。

当 CPU 执行“读”操作时, CPU 会将想要读取数据的地址(二进制)写入 MAR 中,存储体会根据 MAR 中的地址,去寻找对应地址的数据,并将其复制到 MDR 中,最后 CPU 通过数据线路从 MDR 读取数据。

当 CPU 执行“写”操作时, CPU 会发送三个信号:1. 将要写入数据的地址发送给 MAR;2. 将要写入的数据发送给 MDR;3. 发送“写”信号给(主)存储体,告诉存储体本次操作为写操作。

5

存储体内部由一系列存储单元构成,每个存储单元存放一串二进制代码。我们称存储单元里存储的这行二进制代码为“存储字”(word)。word 的长度称为字长。每个存储单元都有对应的地址(数据在存储体内以地址存储)。

而在硬件上,存储单元由一系列存储元(电容)构成,每个存储元的数值以高电平代表 “1”,低电平代表 “0”

因此,MAR 位数反映了存储单元个数,MDR 位数等于字长

例如:MAR 存储为 “0010”,则对应存储体内的第 3 个存储单元。

字(word)没有明确的规定,它和存储器的硬件设计有关:如果存储单元长度是 8 bit,那么字长为 8 bit;如果是 16 bit,那么字长为 16 bit。

word 不等于 Byte

运算器#

6

运算器由图中结构组成,其中 ACC、MQ、X 都是用于存储操作数或运算结果的(相当于告诉 ALU 要做什么运算和用什么数运算),而 ALU 是实现运算的核心元件。

控制器#

7

控制器内部由以上三部分组成,其中核心元件是 CU。PC 是作为指针(存放指令地址)存在的。

完成一条指令(高级程序语言编译为汇编指令)的流程:

  1. PC 从存储器里读取要执行程序的指令的地址,然后从存储器里取出这一条指令的内容(类似 CPU 的读操作)
  2. 然后将该指令存储到 IR 里,CU 再对该指令进行分析,理解指令意图
  3. 当 CU 分析完毕后,会控制其他部件相互配合,完成该指令

一般第一点和第二点合成“取指”阶段,第三点称为“执行”阶段。

计算机的工作流程#

CPU 一般由运算器和控制器两部分组成

9

当执行以上的高级程序时,将其编译成二进制文件,装入主存时如图中表格。

8

()代表寄存器里存储的值,例如 (PC)=0 代表 PC 里此时存储的值为 0

主存里前五个单元存储的是 C 语言编译后的指令,后四个单元存储的是数据(变量值)

M(MAR) 即 Memory(MAR),存储体里位于地址为 (MAR)的数据

  1. PC 值为 0,指向第一个存储单元
  2. PC 将值(0)传送到 MAR 中,因此 MAR 值为 0
  3. 存储体将读取 MAR,将对应地址的数据传入 MDR
  4. IR 通过数据线读取 MDR 的值
  5. IR 把操作数传到 CU,CU 分析得到此为 “取数” 指令
  6. CU 控制 IR,将 IR 中的地址码发送到 MAR
  7. 存储体读取 MAR,把 (MAR)位置的数据发送到 MDR
  8. 然后 CU 控制数据线,将 MDR 的值传入运算器里的 ACC 中
  9. 最后 PC 计数器自动 “+1”

其中前 4 步称为 “取指令”,第五步称为 “分析指令”,后 3 步称为“执行”指令

10

由于 PC 自动 +1,所以此时 PC 指向第二条指令(主存里地址为 1)

  1. (PC)=1,将其传入 MAR
  2. 存储器根据 MAR 的值,把对应地址的数据放入 MDR 中
  3. IR 读取 MDR 的内容
  4. IR 把内容中的操作数发送给 CU
  5. CU 分析该指令含义,得知此为 “乘法” 指令
  6. CU 控制 IR,把 IR 中存储的地址码发送给 MAR
  7. 存储器根据 MAR 的值,把对应地址的数据放入 MDR 中
  8. CU 控制数据线,把 (MDR) 发送到运算器的 MQ
  9. CU 控制数据线,把(ACC)送入 X 寄存器中
  10. CU 通知 ALU 执行乘法运算,并将结果存入 ACC 中

同理,前四步是“取指令”,第五步是“分析指令”,后续为“执行乘法指令”。完成执行指令步骤后, PC 自动加一。

11

同理,不再赘述。

12

前五步:取指令、分析指令没有任何区别。

  1. CU 控制 IR,将 IR 中的地址吗送到 MAR
  2. CU 控制 ACC,将 (ACC)送到 MDR
  3. CU 通过数据线,向主存发送“写”信号,通知存储体将(MDR)写入地址为(MAR)的存储单元

总结

13

取指令、分析指令步骤没有区别,CU 需要分析完指令后才知道接下来要执行什么指令

总结#

14

常考红框内容

在现代计算机体系里,MAR、MDR 通常集成在 CPU 中。或者说,CPU 实际上由控制器、运算器和一些寄存器(MAR、MDR)构成。

计算机软件#

15

计算机软件分为应用软件和系统软件。系统软件为上层的应用软件提供基础服务,包括数据库服务、语言处理(转义、编译)服务、数据库管理系统、操作系统、程序调试服务等。

三种语言#

16

现代一般使用高级语言进行程序的编写,然后使用编译器将其翻译成汇编语言,再使用汇编器将汇编语言翻译成机器可执行的机器语言。机器语言可被机器直接执行,汇编和高级都不行。

显然,越接近底层(硬件),执行的效率越高。因此低级语言的执行效率一般都高于高级语言。

但有的编译器提供一步到位的编译程序:将高级语言直接翻译为机器语言。

有的语言使用解释器进行机器语言的翻译,如 python、JS 和 shell 脚本

解释程序和编译程序的异同

相同:二者都是为了将高级语言翻译为机器语言程序

编译程序是将高级语言编写的源程序一次性全部翻译为机器语言,再执行机器语言程序(只翻译一次)

解释程序类似同生传译,将源程序的一条语句翻译成机器语言后立即执行,再翻译下一句高级语言(每次执行都需要翻译)

因此,编译程序的编译时间较长,但运行速度更快;解释程序反之。

软件和硬件的逻辑功能是等价的#

17

例如用户有一个需求:计算 985*6 = ?

该图指示了软件和硬件可实现同一个功能,但衡量的依据则为成本和性能。要想性能更好,那么则可在硬件上实现更多的逻辑,但成本自然更贵;如果想降低成本,则整个功能在软件上实现的部分更多。

ISA(instruction set architecture)是计算机软件和硬件的关键接口,也就是为软件提供硬件的 API 接口,规定了底层硬件支持哪些汇编指令。

18

计算机系统的层次结构#

19

“虚拟”:意思是指看起来程序编写好后不需要执行编译转换成机器语言,就可以在计算机上运行,实际上底层是仍然需要的。计算机领域的一个术语命名,无需多注意。

系统划分依据

  • M1:使用机器语言执行指令的机器,即执行二进制转换后的机器语言
  • M0:对于一条机器指令,实际上又可以被分解为多条“微指令”。这些微指令由硬件直接执行。例如在前文的[计算机的工作流程](# 计算机的工作流程)中,一条存储于存储器中的二进制机器指令,实际上要经过多条微指令完成:取指令、分析指令、执行指令
  • M3:汇编语言机器用于将汇编程序翻译成机器语言程序,一般是直接与 M1 连接。
  • M2:但由于部分 M3 会调用到系统层级的服务(指令),因此在 M3 和 M1 直接又可以划分一层 M2,它向上提供一些系统服务的调用(给个别名“广义指令”)
  • M4:不必多说,使用编译器将高级语言翻译成汇编程序

从 C 语言到可执行文件#

重点:记得一个 C 文件编译成可执行文件的流程即可。

20

以该文件(hello.cpp)为例子:

#include<stdio.h>
#include<algorithm.h>
# PI = 3.14
int main(void):
{
    printf_s("%.2f",PI+2)
}
c

C 语言源程序经过编写后,会:

  1. 经过预处理器(cpp)对程序开头中的宏定义量,即以字符 # 的指令进行处理。此时它会将头文件的内容给完全复制到当前文件中,并且将程序里的所有使用了宏定义常量 PI 全部替换为数据 3.14。即 PI+2 变为 3.14 + 2 ,并得到 hello.i 文件,此时仍然是高级语言
  2. hello.i 文件经过编译器处理,将高级语言翻译成一条条汇编语言,得到汇编语言程序 hello.s
  3. 汇编器对 hello.s 进行翻译,处理成机器可理解的二进制机器语言程序 hello.o (object)
  4. 由于文件里对一些其他库(文件)的函数做了引用(如 printf),因此其他库文件也同时会被翻译成目标模块(即 .o 文件),例如 printf.o
  5. 最后通过连接器 ( ld )将所有目标程序(模块)链接起来,构建成一个完整的机器语言程序,或者说可执行文件 hello.exe

该可执行程序最后存储于辅存(硬盘)中

21

当需要执行该程序时,计算器会将其加载到主存中,供 CPU 进行访问,同时可通过 IO 设备和程序交互。

计算机性能指标#

存储器的性能指标:总容量#

22

MAR 的位数代表了可表示 2n2^n 个地址序号,MDR 是字长,即一个存储单元的长度。因此

总容量=存储单元个数 × 存储字长 bit总容量 = 存储单元个数\ \times\ 存储字长\ bit

常用转换:

210记为 1 Kb220记为 1 Mb230记为 1 Gb240记为 1 Tb2^{10} 记为\ 1\ Kb, 2^{20} 记为\ 1\ Mb,2^{30} 记为\ 1\ Gb, 2^{40} 记为\ 1\ Tb,

CPU 的性能指标#

CPU 时钟周期#

机器内主时钟脉冲的宽度,是 CPU 工作的最小时间单位。即一串脉冲里,相邻高电平上升沿/下降沿的时间差。单位:Hz

主频(CPU 时钟频率)#

机器内部主时钟的频率,即时钟周期的倒数。对同一类计算器,主频越高,指令执行的每个步骤需要的时间越短,计算速度越快。

也可理解为每秒包含的时钟周期个数(脉冲个数)

CPI#

执行一条指令需要花费的时钟周期数。

执行一条指令的耗时=CPI×CPU 时钟周期执行一条指令的耗时 = CPI \times \text{CPU 时钟周期}

CPU 执行时间#

运行一个完整的程序需要花费的时间

CPU执行时间=CPU 时钟周期数/主频=(指令条数×CPI)÷主频CPU 执行时间 = \text{CPU 时钟周期数}/主频 = (指令条数 \times CPI)\div 主频

23

此处 K、M、G、T 等都是数量单位的缩写,例如 3×106FLOPS=3×103KFLOPS3\times10^6 \text{FLOPS} = 3\times10^3\text{KFLOPS}

示例

24

CPU执行时间 = 指令条数 * CPI * 时钟周期(主频)
plaintext

系统整体的性能指标#

数据通路带宽解释如图。示例:假如有一个 16 bit 大小的包要传送,如果通路带宽为 8 比特,那么需要传两次(两个时钟周期),如果为 16 比特,只需要一个时钟周期即可完成

25

基准程序#

基准程序用于动态评测系统的整体性能,白话就是跑分软件,例如鲁大师。

思考题#

主频高的 CPU 一定比主频低的 CPU 快么#

未必。假设两个 CPU:A 的主频为 2GHz,B 为 1GHz,但是, A 的 CPI 为 10,B 的为 1。那么执行一条指令的耗时:A 为 5 ,B 为 1(CPI÷主频),显然 B 更快

A、B 两个 CPU 的 CPI 相同,那么 A 一定快么#

不一定,虽然 A 的主频更高,但是还需要看硬件上指令系统的实现:如果 A 不支持乘法指令, B 支持,那么 A 只能使用多次加法指令去等效 B 的乘法指令。显然 B 会更快

基准程序的跑分 score 越高(运行速度越快),说明机器越好么#

基准程序中的评测语句存在频率差异,有的更偏向测试显卡 gpu 的计算速度(图像处理速度),有的更偏向 cpu 的计算速度。由于权重不一样,因此结果仅供参考(笑)。

总结#

核心: CPU 中几个参量的计算

26

计算机系统概述
Author Juyao Huang
Published at March 14, 2026
Comment seems to stuck. Try to refresh?✨