导读
大家好,很高兴又和大家见面啦!!!
在上一篇内容中我们介绍了计算机软件与计算机系统的层次结构的相关内容,我们先来简单的回顾一下:
- 计算机软件按功能分类可分为系统软件与应用软件;
- 计算机语言可分为三个级别:
- 机器语言——计算机唯一可以直接识别和执行的语言
- 汇编语言——通过英文大词或其缩写代替二进制的指令代码
- 高级语言——为了方便程序设计人员写出解决问题的处理方案和解题过程的程序
- 除了机器语言外,其它的机器语言都需要借助翻译程序才能被计算机识别。翻译程序可以分为三类:
- 汇编程序(汇编器)——将汇编语言程序翻译成机器语言程序
- 解释程序(解释器)——将源程序中的语句按执行顺序逐条翻译成机器指令并立即执行
- 编译程序(编译器)——将高级语言程序翻译成汇编语言或机器语言程序
- 计算机系统层次结构的分层方式目前尚无统一的标准,我们从计算机语言的角度可以将其分为5个层次,从上到下依次是:
- 虚拟机器M4(高级语言机器)——用编译程序翻译成汇编语言程序
- 虚拟机器M3(汇编语言机器)——用汇编程序翻译成机器语言程序
- 虚拟机器M2(操作系统机器)——用机器语言解释操作系统
- 传统机器M1(机器语言机器)——用微程序解释机器指令
- 微程序机器M0(微指令系统)——由硬件直接执行微指令
- 没有配备软件系统的纯硬件系统的机器称为裸机,M2~M4层是有软件实现的虚拟机层。
- 层次之间的关系紧密,下层是上层的基础,上层是下层的扩展。
计算机系统作为硬件与软件的综合体,现在我们已经从硬件层面与软件层面分别了解了一个完整的计算机系统的组成,但是,在计算机系统中,各个部分又是如何进行工作的呢?在今天的内容中,我们将会来探讨一下计算机系统的工作原理;
一、存储器的工作原理
在前面的介绍中,我们知道存储器分为主存储器(内存)和辅助存储器(外存)。主存储器主要由4个部分组成:
- 记录访存地址的地址寄存器
MAR
- 存放二进制信息的存储体
- 暂存从存储器中读或写的信息的数据寄存器
MDR
- 用于产生存储器操作所需的各种时序信号的时序控制逻辑
存储器的整个工作流程可以看做3步:
- 取址——从
MAR
中取出地址 - 查找——在存储体中按照地址找到对应的数据或指令
- 取值——将数据或指令暂存在
MDR
中。
在整个工作流程中,时序控制逻辑就是来控制各个阶段的执行操作,就比如在取址阶段,需要进行工作的是MAR
,那么时序控制逻辑就会产生MAR所需要的时序信号,此时的存储体与寄存器是处于空闲状态;同理,在存储体和MDR
需要进行工作时,时序控制逻辑都会产生相应的时序信号。
在前面介绍硬件时,我们是以校长找同学的例子来说明存储器的整个工作流程,如果这个例子不够形象,难以理解的话,没关系,我们来换一种方式来理解存储器的工作原理。
简单来讲,存储器的工作原理实际上就是日常生活中的排队取号与叫号。这里我以点外卖为例来说明存储器的工作原理;
我们点外卖时,此时涉及到3个对象,我们这些点餐的顾客,接单的商家以及进行配送的外卖员。
-
从顾客的角度来看,顾客需要经历3个阶段:点餐、取餐、就餐。
- 点餐的过程实际上就是计算机从
MAR
进行取址的过程。我们在点餐时,会根据我们点餐的信息生成一份订单,生成的这份订单就是我们接下来取餐的依据; - 取餐的过程实际上就是计算机在存储体中通过获取到的地址信息进行查找数据的过程。我们在取餐时,我们就需要根据我们下单时生成的订单信息来进行取餐;
- 就餐的过程就是数据存储到
MDR
的过程。当我们取到餐后,我们便会拿回宿舍进行就餐,此时的外卖会被暂时转移到我们的宿舍,之后迎接他的将是被我们吃掉的命运。
- 点餐的过程实际上就是计算机从
-
从商家的角度来看,商家需要经历3个阶段:接单、备餐、出餐。
- 接单的过程就是计算机从
MAR
进行取址的过程。顾客在进行下单后,商家便会收到一份订单,订单中会显示需要商家准备的商品内容; - 备餐的过程就是计算机根据地址信息在存储体中获取数据的过程。商家在收到订单后,便会根据订单的内容准备相应的商品;
- 出餐的过程就是数据暂存到
MDR
的过程。商家在完成备餐后,便会将备好的商品暂时存放在指定的位置等待外卖员来取餐。
- 接单的过程就是计算机从
-
从外卖员的角度来看,外卖员需要经历3个阶段:接单、取餐、送餐。
- 接单的过程就是计算机从
MAR
进行取址的过程。商家在完成接单后,外卖员便会接到对应的订单,订单中显示了商家的地址以及需要获取的商品信息; - 取餐的过程就是计算机根据地址信息在存储体中获取数据的过程。外卖员在到达店铺之后,便会根据获取到的订单信息获取指定的商品;
- 送餐的过程就是数据存储到
MDR
的过程。外卖员在获取到商品后,这个商品就会暂时存放在外卖员的手中,当被送达到指定地点后,又会暂时存放在该地点处等待下一步的操作,也就是顾客取餐并就餐。
- 接单的过程就是计算机从
相信大家现在通过这三种角度的解释,应该能够理解存储器的整个工作原理了,接下来我们就来看看CPU
的工作原理;
二、CPU
的工作原理
中央处理器(CPU
)是将运算器和控制器集成到同一个芯片上,并且CPU
和主存储器共同构成了主机。
接下来我们借助一个具体的C语言代码来说明CPU的整个工作原理:
void test() {
int a = 10;
int b = 20;
int c = 30;
int d = a + b * c;
printf("d = %d\n", d);
}
在这个代码中,我们定义了4个整型变量,并且将前3个变量进行算术运算后的值赋值给了变量d,最后完成了变量d的值的打印操作。整个代码理解起来很简单,下面我们就来看一下对于这个程序,CPU是如何进行处理的,如下所示:
有看过【函数栈帧的创建与销毁】的朋友对这张图应该不陌生了,中间的界面就是反汇编的界面。
这时有朋友可能就会比较好奇,这些东西是如何得来的?为了解答大家的疑惑,我们在正式介绍CPU的工作原理之前,我们需要先了解一下C语言程序从源程序到可执行程序的过程;
2.1 C语言程序从源程序到可执行程序
对于一台计算机而言,它是无法识别通过高级语言编写的程序的,为了能够正常运行高级语言编写的程序,这些程序都需要优先被翻译成机器语言程序之后才能够正常执行。
而在C语言程序中,它被翻译成机器语言总共需要经历4个阶段:
- 预处理阶段:将源程序中以字符
#
开头的命令进行处理,如将引用的头文件进行展开插入到程序文件中,将#define
定义的标识符替换成对应的数值等,最后会生成一个.i
为后缀的源文件xxx.i
; - 编译阶段:通过编译器将预处理后的源文件进行编译,生成一个以
.s
为后缀的汇编语言源程序。汇编语言源程序中的每条语句都以一种文本格式描述了一条低级机器语言指令; - 汇编阶段:汇编器将
.s
文件翻译成机器语言指令,并把这些指令打包成一个称为可重定位目标文件的.o
文件,它是一种二进制文件,因此用文本编辑器打开会显示乱码; - 链接阶段:链接器将多个可重定位目标文件和标准库函数所在的可重定位目标模块文件进行合并,生成一个可执行目标文件,或简称可执行文件。也就是将
.o
为后缀的文件合并成.exe
为后缀的文件。最终生成的可执行文件会被保存在磁盘上。
在这4个阶段中,编译阶段生成的.s
文件就是我们现在看到的反汇编界面的内容。也就是说,这里面展示的就是该程序对应的汇编语言源程序,我们看到的这些指令就是低级的机器语言指令。
在理解了反汇编文件的由来后,下面我们就可以继续探讨在这个程序中的CPU的具体执行过程了;
2.2 指令执行过程
在反汇编界面的最左侧这些数字就是每一行操作对应的地址,中间的英文则是该地址对应的指令,右侧的则是操作对象,如下所示:
函数栈帧开辟的过程这里我就不再展开赘述,感兴趣的朋友可以回顾【函数栈帧的创建与销毁】的内容,这里我们直接来看创建变量a
的这一行指令:
00741955 mov dword ptr [a],0Ah
//00741955——指令地址
//mov——移动指令
//dword ptr——内存单元为4个字节的长度
//0Ah——10,移动对象
//a——接收对象
这行代码完整的含义是将 10
这个整型数值移动到a
这个对象中。
在这个过程中,CPU
会完成3步操作:
- 取指令:
P
C
→
M
A
R
→
存储体
→
M
D
R
→
I
R
PC→MAR→存储体→MDR→IR
PC→MAR→存储体→MDR→IR
-
(
P
C
)
→
M
A
R
(PC)→MAR
(PC)→MAR:此时存放当前欲执行指令地址的寄存器PC存放的就是
00741955
这条指令地址,PC
将这条指令地址送到MAR
之后,PC便会进行自动+1操作,使其存放的内容为下一条指令的地址; -
(
M
A
R
)
→
存储体
(MAR)→存储体
(MAR)→存储体:
MAR
在接收到指令地址后,会直接将该地址送到存储体中读取对应的指令信息; -
(
存储体
)
→
M
D
R
(存储体)→MDR
(存储体)→MDR:当成功读取到指令信息后,该指令信息会被存放到
MDR
中; -
(
M
D
R
)
→
I
R
(MDR)→IR
(MDR)→IR:
MDR
在接受到指令信息后,会将指令信息传送到IR
中;
-
(
P
C
)
→
M
A
R
(PC)→MAR
(PC)→MAR:此时存放当前欲执行指令地址的寄存器PC存放的就是
- 分析指令:
I
R
→
C
U
IR→CU
IR→CU
-
O
P
(
I
R
)
→
C
U
OP(IR)→CU
OP(IR)→CU:存放在
IR
中的指令信息会被IR
送往CU
进行对应指令的分析。在这个例子中,CU
在完成分析后会得到一个移动的指令,因此后续的操作是完成10这个数值的移动。
-
O
P
(
I
R
)
→
C
U
OP(IR)→CU
OP(IR)→CU:存放在
- 执行指令:
I
R
→
M
A
R
→
存储体
IR→MAR→存储体
IR→MAR→存储体
-
A
d
(
I
R
)
→
M
A
R
Ad(IR)→MAR
Ad(IR)→MAR:在
CU
发出控制信号后,IR
会将a
的地址码送到MAR
中; -
(
M
A
R
)
→
存储体
(MAR)→存储体
(MAR)→存储体:
MAR
在收到地址码后,会将该地址送到存储体中,并在该地址的空间中写入10这个数值;
-
A
d
(
I
R
)
→
M
A
R
Ad(IR)→MAR
Ad(IR)→MAR:在
这里大家一定要注意,图示中的内容是为了帮助大家来理解CPU运行的整个过程,并不是代表存储体的存储形式就是如上图所示那样,存储体具体是如何存储数据的这个点我们不深究,我们只要知道能够通过MAR的地址在存储体中找到对应的数据即可。
对于变量b和变量c的创建这里我就不再过多赘述,整个创建的过程与变量a的创建过程是一致的,接下来我们就来看一下变量d的创建过程:
变量d的创建过程总共有4步指令:
0074196A mov eax,dword ptr [ebp-14h]
0074196D imul eax,dword ptr [ebp-20h]
00741971 add eax,dword ptr [ebp-8]
00741974 mov dword ptr [ebp-2Ch],eax
这4步指令中,前三步分别是在进行数据的移动、数据相乘与数据相加,只有最后一步才是创建变量d并完成赋值操作。接下来我们就来看一下在前三步中CPU是如何进行工作的;
- 取指令:
P
C
→
M
A
R
→
存储体
→
M
D
R
→
I
R
PC→MAR→存储体→MDR→IR
PC→MAR→存储体→MDR→IR
-
(
P
C
)
→
M
A
R
(PC)→MAR
(PC)→MAR:PC此时存储的操作码地址是
0074196A
,在PC将该地址传给MAR后,便自动+1存储下一步的操作码地址; -
(
M
A
R
)
→
存储体
(MAR)→存储体
(MAR)→存储体:
MAR
在接收到指令地址后,会直接将该地址送到存储体中读取对应的指令信息; -
(
存储体
)
→
M
D
R
(存储体)→MDR
(存储体)→MDR:当成功读取到指令信息后,该指令信息会被存放到
MDR
中; -
(
M
D
R
)
→
I
R
(MDR)→IR
(MDR)→IR:
MDR
在接受到指令信息后,会将指令信息传送到IR
中;
-
(
P
C
)
→
M
A
R
(PC)→MAR
(PC)→MAR:PC此时存储的操作码地址是
在取址阶段与前面的步骤是一致的只是在整个过程中传输的数据发生了变化;
- 分析指令:
I
R
→
C
U
IR→CU
IR→CU
-
O
P
(
I
R
)
→
C
U
OP(IR)→CU
OP(IR)→CU:存放在
IR
中的指令信息会被IR
送往CU
进行对应指令的分析。此时虽然同样是mov
指令,但是从代码中我们可以看到,此时的mov
对象与接收对象是有一定区别的,这时的mov
更像是一个取数指令;
-
O
P
(
I
R
)
→
C
U
OP(IR)→CU
OP(IR)→CU:存放在
- 执行指令:
I
R
→
M
A
R
→
存储体
→
M
D
R
→
E
A
X
IR→MAR→存储体→MDR→EAX
IR→MAR→存储体→MDR→EAX
-
A
d
(
I
R
)
→
M
A
R
Ad(IR)→MAR
Ad(IR)→MAR:在
CU
发出控制信号后,IR
会将b
的地址码送到MAR
中; -
(
M
A
R
)
→
存储体
(MAR)→存储体
(MAR)→存储体:
MAR
在收到地址码后,会将该地址送到存储体中。- 此时的地址包含的信息与前面的三次创建变量时稍有不同,前面在这一步
MAR
在传输地址时同时传输的是一个写的信号,存储体在接收到该信号后,会在指定的地址进行写入,因此前面的创建过程,在执行阶段,存储体完成数据的写入后就结束了; - 但是这里
MAR
在传输地址的同时传输的则是一个读的信号,存储体在接收到该信号后,会在指定的地址中读取对应的数据;
- 此时的地址包含的信息与前面的三次创建变量时稍有不同,前面在这一步
-
(
存储体
)
→
M
D
R
(存储体)→MDR
(存储体)→MDR:由于此时传入到存储体中的是读信号,因此,存储体中指定地址的数据会被读取出来并存放到
MDR
中; -
(
M
D
R
)
→
E
A
X
(MDR)→EAX
(MDR)→EAX:在执行阶段与取址阶段不同的是,
MDR
此时接收到的数据会根据具体的操作信号将数据传输到指定位置,就比如本例中的EAX
寄存器;
-
A
d
(
I
R
)
→
M
A
R
Ad(IR)→MAR
Ad(IR)→MAR:在
这里可能有朋友不知道EAX
是啥,EAX
属于运算器中的通用寄存器的一种,可以看做是数据在进行运算前的一个临时中转站。在之后的操作中我们就会看到CPU在完成取址与分析两步操作后,执行的是imul
操作,也就是乘法操作,将变量c的值通过乘商寄存器(MQ
)与寄存器EAX
的值进行相乘,相乘后的结果同样是存储在EAX
中,如下所示:
再下一步就是进入了加法阶段,此时MDR
传输的数据会经由累加器(ACC
)与EAX
中存储的值进行相加,相加后的结果继续存储在EAX
中,如下所示:
当完成以上操作后,此时的EAX
中存储的就是我们在创建变量d时需要对其进行初始化的值,因此在创建变量d的最后一步写入阶段,是直接从EAX
中将值写入变量d中,如下所示:
那具体是不是这么一个过程呢?下面我们通过反汇编的窗口来验证一下:
可以看到,当完成变量d的创建后,此时寄存器eax
与变量d的空间中存储的都是0x00000262
这个值。
2.3 注意
现在大家通过这个例子应该就能理解CPU
在实际运行过程中的一个过程了吧。
但是我们在进行理解时需要注意几个点:
- 这里我们给的图示比较简陋,不能够准确的描述出
CPU
实际运行过程中的具体过程,这里只能辅助大家来进行理解; - 在整个执行过程中,并不是说该部件想要做啥就能够做啥的,实际上所有的工作都是需要通过控制信号来进行控制;
- 在上述的过程中,由于取址与分析的过程都是一致的,唯一不同的就是各个部件之间的传输数据不同,因此在后续的介绍中我们省略了取址与分析这两步;
- 在文字表述中有朋友可能会注意到,有些部件的外面有加一个
()
,而有些则没有。实际上这里加上()
表示的是该部件中的内容,如 ( P C ) → M A R (PC)→MAR (PC)→MAR表示的是将PC
中的数据传输到MAR
中。因此建议大家在手动书写时,一定要记得通过()
来区分此时操作的是数据还是硬件
结语
在今天的内容中,我们介绍了存储器的工作原理和CPU
的工作原理的内容:
- 对于存储器而言,它的整个工作原理就类似于现实生活中的取号叫号的过程。通过从
MAR
中获取地址信息,在通过地址信息找到存储体中对应地址所存储的数据,最后由MDR
来记录读取到的数据; - 对于
CPU
而言,它的整个工作原理就是通过控制信号完成的一个按部就班的操作。整个操作过程分为三个阶段:- 取址阶段:通过从
PC
中取出当前需要执行的指令的地址,再从存储体中取出当前地址中存放的指令与数据信息,最后将这些信息存放入IR
中; - 分析阶段:通过将
IR
中存放的指令信息传输到CU
中进行分析来获取下一步的指令信号; - 执行阶段:通过
CU
传输的指令信号,各个硬件会根据具体的信号内容来执行相关的操作,如读/写存储体指定地址中的数据、数据的运算等等
- 取址阶段:通过从
- 正因为
CPU
的各个阶段的明确划分,因此CPU在识别当前的是指令还是数据时,只需要看它目前所处的运行阶段即可;
今天的内容到这里就全部结束了,在下一篇内容中我们将介绍《计算机的性能指标》的相关内容,大家记得关注哦!如果大家喜欢博主的内容,可以点赞、收藏加评论支持一下博主,当然也可以将博主的内容转发给你身边需要的朋友。最后感谢各位朋友的支持,咱们下一篇再见!!!