冯诺伊曼架构#
”存储程序”的概念#
存储程序是为了解决早期 ENIAC 机时由人类手动接线来控制计算的问题。
其核心理念:将编译好的程序和初始数据存入计算机的主存储器,由计算机读取在主存中的首地址来执行程序的第一条指令,由此实现自动、连续的取指令并执行的操作。
架构图#

即由 Input 设备输入数据,将其传给运算器,由运算器决定存储、输出。
特点#
- 由五个部分组成:运算、控制、存储, IO
- 指令和数据以相同的形式存储于存储器:都是按照地址访问
- 指令和数据都以二进制形式存储(废话)
- 指令由 操作码 和 地址码 组成。操作码:加、减等操作
- 以运算器为中心
现代计算器架构#
现代计算器在冯架构上改进,为了提高性能,由以运算器为中心改为以存储器为核心。

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

主存与辅存:
主存指的是计算机的内存,辅存指的是电脑的固态硬盘、机械硬盘。
辅存存储的是程序和代码,例如手机的 APP;而主存则是程序运行时,才会把程序加载到内存里执行。
计算机的功能部件#
存储器#

存储器内部主要部件为 存储体、 MAR 和 MDR。
MAR 为地址寄存器,用于存放 CPU 想要访问的存储地址。MDR 为数据寄存器,用于存放存储体提供给 CPU 的对应地址的数据。
当 CPU 执行“读”操作时, CPU 会将想要读取数据的地址(二进制)写入 MAR 中,存储体会根据 MAR 中的地址,去寻找对应地址的数据,并将其复制到 MDR 中,最后 CPU 通过数据线路从 MDR 读取数据。
当 CPU 执行“写”操作时, CPU 会发送三个信号:1. 将要写入数据的地址发送给 MAR;2. 将要写入的数据发送给 MDR;3. 发送“写”信号给(主)存储体,告诉存储体本次操作为写操作。

存储体内部由一系列存储单元构成,每个存储单元存放一串二进制代码。我们称存储单元里存储的这行二进制代码为“存储字”(word)。word 的长度称为字长。每个存储单元都有对应的地址(数据在存储体内以地址存储)。
而在硬件上,存储单元由一系列存储元(电容)构成,每个存储元的数值以高电平代表 “1”,低电平代表 “0”
因此,MAR 位数反映了存储单元个数,MDR 位数等于字长
例如:MAR 存储为 “0010”,则对应存储体内的第 3 个存储单元。
字(word)没有明确的规定,它和存储器的硬件设计有关:如果存储单元长度是 8 bit,那么字长为 8 bit;如果是 16 bit,那么字长为 16 bit。
word 不等于 Byte
运算器#

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

控制器内部由以上三部分组成,其中核心元件是 CU。PC 是作为指针(存放指令地址)存在的。
完成一条指令(高级程序语言编译为汇编指令)的流程:
- PC 从存储器里读取要执行程序的指令的地址,然后从存储器里取出这一条指令的内容(类似 CPU 的读操作)
- 然后将该指令存储到 IR 里,CU 再对该指令进行分析,理解指令意图
- 当 CU 分析完毕后,会控制其他部件相互配合,完成该指令
一般第一点和第二点合成“取指”阶段,第三点称为“执行”阶段。
计算机的工作流程#
CPU 一般由运算器和控制器两部分组成

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

()代表寄存器里存储的值,例如(PC)=0代表 PC 里此时存储的值为 0主存里前五个单元存储的是 C 语言编译后的指令,后四个单元存储的是数据(变量值)
M(MAR)即 Memory(MAR),存储体里位于地址为 (MAR)的数据
- PC 值为 0,指向第一个存储单元
- PC 将值(0)传送到 MAR 中,因此 MAR 值为 0
- 存储体将读取 MAR,将对应地址的数据传入 MDR
- IR 通过数据线读取 MDR 的值
- IR 把操作数传到 CU,CU 分析得到此为 “取数” 指令
- CU 控制 IR,将 IR 中的地址码发送到 MAR
- 存储体读取 MAR,把 (MAR)位置的数据发送到 MDR
- 然后 CU 控制数据线,将 MDR 的值传入运算器里的 ACC 中
- 最后 PC 计数器自动 “+1”
其中前 4 步称为 “取指令”,第五步称为 “分析指令”,后 3 步称为“执行”指令

由于 PC 自动 +1,所以此时 PC 指向第二条指令(主存里地址为 1)
- (PC)=1,将其传入 MAR
- 存储器根据 MAR 的值,把对应地址的数据放入 MDR 中
- IR 读取 MDR 的内容
- IR 把内容中的操作数发送给 CU
- CU 分析该指令含义,得知此为 “乘法” 指令
- CU 控制 IR,把 IR 中存储的地址码发送给 MAR
- 存储器根据 MAR 的值,把对应地址的数据放入 MDR 中
- CU 控制数据线,把 (MDR) 发送到运算器的 MQ
- CU 控制数据线,把(ACC)送入 X 寄存器中
- CU 通知 ALU 执行乘法运算,并将结果存入 ACC 中
同理,前四步是“取指令”,第五步是“分析指令”,后续为“执行乘法指令”。完成执行指令步骤后, PC 自动加一。

同理,不再赘述。

前五步:取指令、分析指令没有任何区别。
- CU 控制 IR,将 IR 中的地址吗送到 MAR
- CU 控制 ACC,将 (ACC)送到 MDR
- CU 通过数据线,向主存发送“写”信号,通知存储体将(MDR)写入地址为(MAR)的存储单元
总结

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

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

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

现代一般使用高级语言进行程序的编写,然后使用编译器将其翻译成汇编语言,再使用汇编器将汇编语言翻译成机器可执行的机器语言。机器语言可被机器直接执行,汇编和高级都不行。
显然,越接近底层(硬件),执行的效率越高。因此低级语言的执行效率一般都高于高级语言。
但有的编译器提供一步到位的编译程序:将高级语言直接翻译为机器语言。
有的语言使用解释器进行机器语言的翻译,如 python、JS 和 shell 脚本
解释程序和编译程序的异同:
相同:二者都是为了将高级语言翻译为机器语言程序
编译程序是将高级语言编写的源程序一次性全部翻译为机器语言,再执行机器语言程序(只翻译一次)
解释程序类似同生传译,将源程序的一条语句翻译成机器语言后立即执行,再翻译下一句高级语言(每次执行都需要翻译)
因此,编译程序的编译时间较长,但运行速度更快;解释程序反之。
软件和硬件的逻辑功能是等价的#

例如用户有一个需求:计算 985*6 = ?
该图指示了软件和硬件可实现同一个功能,但衡量的依据则为成本和性能。要想性能更好,那么则可在硬件上实现更多的逻辑,但成本自然更贵;如果想降低成本,则整个功能在软件上实现的部分更多。
ISA(instruction set architecture)是计算机软件和硬件的关键接口,也就是为软件提供硬件的 API 接口,规定了底层硬件支持哪些汇编指令。

计算机系统的层次结构#

“虚拟”:意思是指看起来程序编写好后不需要执行编译转换成机器语言,就可以在计算机上运行,实际上底层是仍然需要的。计算机领域的一个术语命名,无需多注意。
系统划分依据:
- M1:使用机器语言执行指令的机器,即执行二进制转换后的机器语言
- M0:对于一条机器指令,实际上又可以被分解为多条“微指令”。这些微指令由硬件直接执行。例如在前文的[计算机的工作流程](# 计算机的工作流程)中,一条存储于存储器中的二进制机器指令,实际上要经过多条微指令完成:取指令、分析指令、执行指令
- M3:汇编语言机器用于将汇编程序翻译成机器语言程序,一般是直接与 M1 连接。
- M2:但由于部分 M3 会调用到系统层级的服务(指令),因此在 M3 和 M1 直接又可以划分一层 M2,它向上提供一些系统服务的调用(给个别名“广义指令”)
- M4:不必多说,使用编译器将高级语言翻译成汇编程序
从 C 语言到可执行文件#
重点:记得一个 C 文件编译成可执行文件的流程即可。

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

当需要执行该程序时,计算器会将其加载到主存中,供 CPU 进行访问,同时可通过 IO 设备和程序交互。
计算机性能指标#
存储器的性能指标:总容量#

MAR 的位数代表了可表示 个地址序号,MDR 是字长,即一个存储单元的长度。因此
常用转换:
CPU 的性能指标#
CPU 时钟周期#
机器内主时钟脉冲的宽度,是 CPU 工作的最小时间单位。即一串脉冲里,相邻高电平上升沿/下降沿的时间差。单位:Hz
主频(CPU 时钟频率)#
机器内部主时钟的频率,即时钟周期的倒数。对同一类计算器,主频越高,指令执行的每个步骤需要的时间越短,计算速度越快。
也可理解为每秒包含的时钟周期个数(脉冲个数)
CPI#
执行一条指令需要花费的时钟周期数。
CPU 执行时间#
运行一个完整的程序需要花费的时间

此处 K、M、G、T 等都是数量单位的缩写,例如
示例:

CPU执行时间 = 指令条数 * CPI * 时钟周期(主频)plaintext系统整体的性能指标#
数据通路带宽解释如图。示例:假如有一个 16 bit 大小的包要传送,如果通路带宽为 8 比特,那么需要传两次(两个时钟周期),如果为 16 比特,只需要一个时钟周期即可完成

基准程序#
基准程序用于动态评测系统的整体性能,白话就是跑分软件,例如鲁大师。
思考题#
主频高的 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 中几个参量的计算
