cpu是如何执行程序的?

一、 引言与核心问题

开篇即抛出几个我们可能"似懂非懂"的问题,作为本章的引导:

  • 代码 a = 1 + 2 到底是怎么被 CPU 执行的?

  • 软件的 32 位和 64 位有什么区别?32 位操作系统能跑在 64 位电脑上吗?反过来呢?

  • 64 位 CPU 比 32 位 CPU 的优势在哪?64 位 CPU 的计算性能一定更高吗?

二、 理解计算模型:图灵机

为了理解程序执行的原理,最基础的"图灵机"讲起。

  • 核心思想:图灵机的基本思想是用机器来模拟人们用纸笔进行数学运算的过程。

  • 基本组成

    1. 纸带 :一条由连续格子组成的纸带,每个格子可以写入字符。这就好比内存,格子里的字符就是内存中的数据或程序。

    2. 读写头:可以读取或写入纸带上任意格子的字符。它包含三个关键部件:

      • 存储单元:存放数据。

      • 控制单元:识别字符是数据还是指令,并控制程序流程。

      • 运算单元:执行运算指令。

1 + 2 为例,图灵机的执行过程:

  1. 写入数据 :读写头将 "1, 2, +" 这 3 个字符分别写入纸带的 3 个格子,并停在 1 对应的格子上。

  2. 读入数据1 :读写头读入 1 ,并存放到存储设备(图灵机的"状态")中。

  3. 读入数据2 :读写头右移一格,用同样的方式读入 2 ,此时图灵机的状态中存储着 12 两个连续数字。

  4. 执行运算 :读写头再右移,碰到 + 号。控制单元识别出这是一个运算符指令,于是通知运算单元工作。运算单元读取状态中的 12,计算出结果 3,再将 3 存回状态中。

  5. 写回结果 :运算单元将结果 3 返回给控制单元,控制单元再将结果传给读写头。读写头右移,将结果 3 写入纸带的下一个格子中。

三、 理解计算机结构:冯·诺依曼模型

冯·诺依曼模型是在图灵机设计思想基础上提出的具体实现报告,它约定了用二进制进行计算和存储,并定义了计算机的 5 个基本部分:

  1. 内存

    • 程序和数据都线性地存储在内存中。

    • 基本单位:字节(Byte),1 字节 = 8 位(bit)。

    • 内存地址从 0 开始编号,直到最后一个地址。这种线性结构使得读写任何地址的速度都是一样的。

  2. 中央处理器(CPU)

    • 32 位 vs 64 位 CPU :最主要区别在于一次能计算多少字节的数据 。32 位 CPU 一次计算 4 个字节,64 位 CPU 一次计算 8 个字节。这通常被称为 CPU 的位宽

    • 位宽的意义 :位宽越大,一次能计算的数值范围就越大。例如,8 位 CPU 只能算 0~255 范围的数,无法一次计算 10000 * 500

    • CPU 内部组件

      • 寄存器 :用于存储计算时马上要用到的数据,速度极快,紧靠控制单元和运算单元。为什么有了内存还要寄存器?因为内存离 CPU 太远了,而寄存器就在 CPU 内部,速度极快。

      • 控制单元:负责控制 CPU 工作。

      • 逻辑运算单元:负责计算。

    • 常见寄存器种类

      • 通用寄存器:存放要进行运算的数据。

      • 程序计数器 :存储 CPU 要执行的下一条指令所在的内存地址

      • 指令寄存器:存储从内存中取出的、当前正在被执行的指令本身。

  3. 总线

    • 用于 CPU、内存和其他设备之间的通信,分为 3 种:

      • 地址总线:指定 CPU 将要操作的内存地址。

      • 数据总线:读写内存中的数据。

      • 控制总线:发送和接收信号,如中断、设备复位等。

  4. 输入/输出设备

    • 输入设备向计算机输入数据,输出设备则输出计算结果。
四、 关键概念深化:线路位宽与 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 执行程序的基本过程(指令周期):

  1. 取指(Fetch):CPU 从"程序计数器"读取下一条指令的内存地址,通过地址总线指定该地址,再通过数据总线从内存中获取指令数据,并将其存入"指令寄存器"。

  2. 译码(Decode):CPU 分析"指令寄存器"中的指令,确定指令类型(如计算、存储)和参数。

  3. 执行(Execution):根据指令类型,交由"逻辑运算单元"计算,或由"控制单元"执行存储等操作。

  4. 程序计数器自增:执行完指令后,"程序计数器"的值自增,指向下一条指令。自增的大小由 CPU 位宽决定,如 32 位 CPU 中一条指令占 4 字节,则程序计数器 +4。

  5. 循环 :CPU 不断重复以上过程,形成一个循环,这就是 CPU 的指令周期

六、 拆解 a = 1 + 2 的执行细节

这部分以 32 位 CPU 为例,将整个流程细化。

  1. 编译 :CPU 不认识 a = 1 + 2 这个字符串。需要先用编译器将其翻译成汇编代码,再由汇编器翻译成由 0 和 1 组成的机器码。这一条条机器码就是计算机指令。

  2. 内存布局 :编译器分析代码,发现 12 是数据,把它们存放到内存的"数据段",发现指令,则存放到"正文段"。

    • 数据 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 的内存地址。
  1. 执行 :程序执行时,"程序计数器"被设置为 0x200,然后 CPU 开始进入指令周期,依次执行这 4 条指令,最终完成 1+2 的计算并将结果存入变量 a
七、 指令的格式与类型
  • 指令编码与解码

    • 编译器将汇编码翻译成机器码的过程叫编码

    • CPU 执行时解析机器码的过程叫解码

    • 示例add R0, R1, R2 这条 MIPS 指令,会被编码成一个 32 位的机器码 0x00011020,其中包含了操作码(add 的功能码)、源寄存器(R0, R1)和目标寄存器(R2)的编号。

  • 指令类型:从功能上分为 5 大类:

    1. 数据传输类 :如 store/loadmov

    2. 运算类:如加减乘除、位运算等。

    3. 跳转类 :通过修改程序计数器值实现,如 if-else,函数调用。

    4. 信号类 :如发生中断的 trap 指令。

    5. 闲置类 :如 nop,CPU 空转一个周期。

八、 指令的执行速度与性能优化
  • CPU 主频与时钟周期

    • 1 GHz 的 CPU 表示时钟频率是 1G,每秒产生 1G 次脉冲信号,一次脉冲就是一个时钟周期。主频越高,时钟周期越短,工作越快。

    • 在一个时钟周期内,CPU 仅能完成一个最基本的动作,大多数指令需要多个时钟周期才能完成

  • 程序执行时间公式

    • 程序的 CPU 执行时间 = CPU 时钟周期数 × 时钟周期时间

    • 进一步拆解:程序的 CPU 执行时间 = 指令数 × 每条指令的平均时钟周期数(CPI) × 时钟周期时间

  • 优化方向(让程序跑得更快)

    1. 减少指令数:主要由编译器优化负责。

    2. 降低 CPI :现代 CPU 通过流水线(Pipeline)技术,将一条指令的取指、译码、执行等多个阶段重叠执行,使得平均下来一个时钟周期就能完成一条指令,降低了 CPI。

    3. 提高主频(缩短时钟周期):也就是提升 CPU 主频,甚至超频,但这会带来散热问题且摩尔定律已放缓。

九、 总结:回答开篇问题

文章最后,点对点地回答了开头提出的问题。

  1. 64 位 CPU 的优势在哪?性能一定更高吗?

    • 优势

      • 计算能力:可一次性计算超过 32 位的数字,而 32 位 CPU 需分步计算,效率较低。

      • 寻址能力 :可以寻址远超 4GB 的内存空间(理论上限为 2^64)。

    • 性能:只有在计算超过 32 位的大数字时,64 位的优势才能体现出来,否则与 32 位性能相差不大。

  2. 软件 32 位/64 位的区别?32 位系统能跑在 64 位机器上吗?反之呢?

    • 区别 :软件的 32 位和 64 位指的是指令的位宽

    • 兼容性

      • 64 位机器运行 32 位程序:可行,通过兼容机制实现。

      • 32 位机器运行 64 位程序:不可行,因为 32 位的寄存器无法容纳 64 位的指令。

    • 核心总结硬件的 64 和 32 位指的是 CPU 的位宽,软件的则指的是指令的位宽。

相关推荐
赵渝强老师1 小时前
【赵渝强老师】金仓数据库的运行日志文件
数据库·postgresql·oracle·国产数据库
D3bugRealm1 小时前
pgvector:PostgreSQL 原生向量搜索扩展
数据库·其他·postgresql
暴力求解2 小时前
Linux---网络基础概念
linux·运维·服务器·网络·操作系统
Java面试题总结2 小时前
PostgreSQL 性能调优:内存、I/O 与连接管理
数据库·postgresql
北秋,2 小时前
Oracle 数据库基础用法
数据库·oracle
CLX05052 小时前
C#怎么实现全局异常过滤器_C#如何捕获控制器报错【核心】
jvm·数据库·python
多加点辣也没关系2 小时前
设计模式-享元模式
数据库·设计模式·享元模式
牢七2 小时前
Mailvelope
数据库
阿里云瑶池数据库2 小时前
如何破解多租户隔离与性能难题?PolarDB PostgreSQL实战指南
数据库·postgresql