一、 引言与核心问题
开篇即抛出几个我们可能"似懂非懂"的问题,作为本章的引导:
-
代码
a = 1 + 2到底是怎么被 CPU 执行的? -
软件的 32 位和 64 位有什么区别?32 位操作系统能跑在 64 位电脑上吗?反过来呢?
-
64 位 CPU 比 32 位 CPU 的优势在哪?64 位 CPU 的计算性能一定更高吗?
二、 理解计算模型:图灵机
为了理解程序执行的原理,最基础的"图灵机"讲起。
-
核心思想:图灵机的基本思想是用机器来模拟人们用纸笔进行数学运算的过程。
-
基本组成:
-
纸带 :一条由连续格子组成的纸带,每个格子可以写入字符。这就好比内存,格子里的字符就是内存中的数据或程序。
-
读写头:可以读取或写入纸带上任意格子的字符。它包含三个关键部件:
-
存储单元:存放数据。
-
控制单元:识别字符是数据还是指令,并控制程序流程。
-
运算单元:执行运算指令。
-
-
以 1 + 2 为例,图灵机的执行过程:
-
写入数据 :读写头将 "1, 2, +" 这 3 个字符分别写入纸带的 3 个格子,并停在
1对应的格子上。 -
读入数据1 :读写头读入
1,并存放到存储设备(图灵机的"状态")中。 -
读入数据2 :读写头右移一格,用同样的方式读入
2,此时图灵机的状态中存储着1和2两个连续数字。 -
执行运算 :读写头再右移,碰到
+号。控制单元识别出这是一个运算符指令,于是通知运算单元工作。运算单元读取状态中的1和2,计算出结果3,再将3存回状态中。 -
写回结果 :运算单元将结果
3返回给控制单元,控制单元再将结果传给读写头。读写头右移,将结果3写入纸带的下一个格子中。
三、 理解计算机结构:冯·诺依曼模型
冯·诺依曼模型是在图灵机设计思想基础上提出的具体实现报告,它约定了用二进制进行计算和存储,并定义了计算机的 5 个基本部分:
-
内存
-
程序和数据都线性地存储在内存中。
-
基本单位:字节(Byte),1 字节 = 8 位(bit)。
-
内存地址从 0 开始编号,直到最后一个地址。这种线性结构使得读写任何地址的速度都是一样的。
-
-
中央处理器(CPU)
-
32 位 vs 64 位 CPU :最主要区别在于一次能计算多少字节的数据 。32 位 CPU 一次计算 4 个字节,64 位 CPU 一次计算 8 个字节。这通常被称为 CPU 的位宽。
-
位宽的意义 :位宽越大,一次能计算的数值范围就越大。例如,8 位 CPU 只能算 0~255 范围的数,无法一次计算
10000 * 500。 -
CPU 内部组件:
-
寄存器 :用于存储计算时马上要用到的数据,速度极快,紧靠控制单元和运算单元。为什么有了内存还要寄存器?因为内存离 CPU 太远了,而寄存器就在 CPU 内部,速度极快。
-
控制单元:负责控制 CPU 工作。
-
逻辑运算单元:负责计算。
-
-
常见寄存器种类:
-
通用寄存器:存放要进行运算的数据。
-
程序计数器 :存储 CPU 要执行的下一条指令所在的内存地址。
-
指令寄存器:存储从内存中取出的、当前正在被执行的指令本身。
-
-
-
总线
-
用于 CPU、内存和其他设备之间的通信,分为 3 种:
-
地址总线:指定 CPU 将要操作的内存地址。
-
数据总线:读写内存中的数据。
-
控制总线:发送和接收信号,如中断、设备复位等。
-
-
-
输入/输出设备
- 输入设备向计算机输入数据,输出设备则输出计算结果。
四、 关键概念深化:线路位宽与 CPU 位宽
-
线路传输原理 :通过操作电压的高低来表示二进制的 0 和 1。例如,高低高的电压信号组合就是二进制的
101。 -
串行传输 :如果只有一条线路,一次只能传 1 位,传
101就需要 3 次,效率极低。 -
并行传输:增加线路数量,可以一次传输多位数据。
-
地址总线与内存寻址 :要操作 4GB 的内存,就需要
2^32 = 4G个地址,因此需要 32 条地址总线。CPU 的位宽最好不要小于线路位宽,否则工作会非常复杂。32 位 CPU 搭配 32 位宽的线路效果最好。 -
32 位 CPU 计算 64 位数字 :需要将两个 64 位数各自拆分成高低 32 位,分步计算,效率较低。而 64 位 CPU 可以一次完成。但这只在计算超过 32 位的大数字时才有优势。
-
内存寻址限制:32 位 CPU 最大只能操作 4GB 内存,这是由其地址总线位宽决定的。
五、 程序执行的全过程详解
程序是指令的集合,运行过程就是 CPU 一条一条执行这些指令。
CPU 执行程序的基本过程(指令周期):
-
取指(Fetch):CPU 从"程序计数器"读取下一条指令的内存地址,通过地址总线指定该地址,再通过数据总线从内存中获取指令数据,并将其存入"指令寄存器"。
-
译码(Decode):CPU 分析"指令寄存器"中的指令,确定指令类型(如计算、存储)和参数。
-
执行(Execution):根据指令类型,交由"逻辑运算单元"计算,或由"控制单元"执行存储等操作。
-
程序计数器自增:执行完指令后,"程序计数器"的值自增,指向下一条指令。自增的大小由 CPU 位宽决定,如 32 位 CPU 中一条指令占 4 字节,则程序计数器 +4。
-
循环 :CPU 不断重复以上过程,形成一个循环,这就是 CPU 的指令周期。
六、 拆解 a = 1 + 2 的执行细节
这部分以 32 位 CPU 为例,将整个流程细化。
-
编译 :CPU 不认识
a = 1 + 2这个字符串。需要先用编译器将其翻译成汇编代码,再由汇编器翻译成由 0 和 1 组成的机器码。这一条条机器码就是计算机指令。 -
内存布局 :编译器分析代码,发现
1和2是数据,把它们存放到内存的"数据段",发现指令,则存放到"正文段"。-
数据
1被存放在地址0x100。 -
数据
2被存放在地址0x104。 -
a = 1 + 2被翻译成 4 条指令,存放在0x200~0x20c:
-
| 地址 | 指令 | 含义 |
|---|---|---|
| 0x200 | load | 将地址 0x100 中的数据(即 1)装入寄存器 R0。 |
| 0x204 | load | 将地址 0x104 中的数据(即 2)装入寄存器 R1。 |
| 0x208 | add | 将寄存器 R0 和 R1 的数据相加,结果存放到寄存器 R2。 |
| 0x20c | store | 将寄存器 R2 中的数据存回数据段的 0x108 地址中,这个地址就是变量 a 的内存地址。 |
- 执行 :程序执行时,"程序计数器"被设置为
0x200,然后 CPU 开始进入指令周期,依次执行这 4 条指令,最终完成1+2的计算并将结果存入变量a。
七、 指令的格式与类型
-
指令编码与解码:
-
编译器将汇编码翻译成机器码的过程叫编码。
-
CPU 执行时解析机器码的过程叫解码。
-
示例 :
add R0, R1, R2这条 MIPS 指令,会被编码成一个 32 位的机器码0x00011020,其中包含了操作码(add 的功能码)、源寄存器(R0, R1)和目标寄存器(R2)的编号。
-
-
指令类型:从功能上分为 5 大类:
-
数据传输类 :如
store/load,mov。 -
运算类:如加减乘除、位运算等。
-
跳转类 :通过修改程序计数器值实现,如
if-else,函数调用。 -
信号类 :如发生中断的
trap指令。 -
闲置类 :如
nop,CPU 空转一个周期。
-
八、 指令的执行速度与性能优化
-
CPU 主频与时钟周期:
-
1 GHz的 CPU 表示时钟频率是 1G,每秒产生 1G 次脉冲信号,一次脉冲就是一个时钟周期。主频越高,时钟周期越短,工作越快。 -
在一个时钟周期内,CPU 仅能完成一个最基本的动作,大多数指令需要多个时钟周期才能完成。
-
-
程序执行时间公式:
-
程序的 CPU 执行时间 = CPU 时钟周期数 × 时钟周期时间
-
进一步拆解:程序的 CPU 执行时间 = 指令数 × 每条指令的平均时钟周期数(CPI) × 时钟周期时间
-
-
优化方向(让程序跑得更快):
-
减少指令数:主要由编译器优化负责。
-
降低 CPI :现代 CPU 通过流水线(Pipeline)技术,将一条指令的取指、译码、执行等多个阶段重叠执行,使得平均下来一个时钟周期就能完成一条指令,降低了 CPI。
-
提高主频(缩短时钟周期):也就是提升 CPU 主频,甚至超频,但这会带来散热问题且摩尔定律已放缓。
-
九、 总结:回答开篇问题
文章最后,点对点地回答了开头提出的问题。
-
64 位 CPU 的优势在哪?性能一定更高吗?
-
优势:
-
计算能力:可一次性计算超过 32 位的数字,而 32 位 CPU 需分步计算,效率较低。
-
寻址能力 :可以寻址远超 4GB 的内存空间(理论上限为
2^64)。
-
-
性能:只有在计算超过 32 位的大数字时,64 位的优势才能体现出来,否则与 32 位性能相差不大。
-
-
软件 32 位/64 位的区别?32 位系统能跑在 64 位机器上吗?反之呢?
-
区别 :软件的 32 位和 64 位指的是指令的位宽。
-
兼容性:
-
64 位机器运行 32 位程序:可行,通过兼容机制实现。
-
32 位机器运行 64 位程序:不可行,因为 32 位的寄存器无法容纳 64 位的指令。
-
-
核心总结 :硬件的 64 和 32 位指的是 CPU 的位宽,软件的则指的是指令的位宽。
-