
文档教程知识库【免费下载链接】CS-Base图解计算机网络、操作系统、计算机组成、数据库共 1000 张图 50 万字破除晦涩难懂的计算机基础知识让天下没有难懂的八股文 在线阅读https://xiaolincoding.com项目地址https://gitcode.com/GitHub_Trending/cs/CS-Base点击查看免费下载本文是 CS-Base 项目《图解系统》硬件结构章节的核心文章对应仓库文件 os/1_hardware/how_cpu_run.md系统讲解一条a 1 2这样的代码是如何被 CPU 一步步执行完的。读者将掌握图灵机与冯诺依曼模型的基本组成、32 位与 64 位 CPU 的本质区别、程序执行的完整指令周期Fetch / Decode / Execution / Store以及机器码、指令集与指令类型的底层知识并能看懂 MIPS 指令如何编码成二进制机器码。从图灵机说起程序执行的原型要想知道程序执行的原理可以先从图灵机说起。图灵的基本思想是用机器来模拟人们用纸笔进行数学运算的过程而且它定义了计算机由哪些部分组成、程序又是如何执行的。图灵机的基本组成如下有一条纸带纸带由一个个连续的格子组成每个格子可以写入字符。纸带就好比内存纸带上的格子的字符就好比内存中的数据或程序有一个读写头可以读取纸带上任意格子的字符也可以把字符写入到纸带的格子读写头上有一些部件比如存储单元、控制单元以及运算单元存储单元用于存放数据控制单元用于识别字符是数据还是指令以及控制程序的流程等运算单元用于执行运算指令。用图灵机计算 1 2以简单数学运算1 2为例看看它是怎么执行这行代码的首先用读写头把「1、2、」这 3 个字符分别写入到纸带上的 3 个格子然后读写头先停在 1 字符对应的格子上接着读写头读入 1 到存储设备中这个存储设备称为图灵机的状态然后读写头向右移动一个格用同样的方式把 2 读入到图灵机的状态于是现在图灵机的状态中存储着两个连续的数字 1 和 2读写头再往右移动一个格就会碰到 号。读写头读到 号后将 号传输给「控制单元」控制单元发现是一个 号而不是数字所以没有存入到状态中因为 号是运算符指令作用是加和目前的状态于是通知「运算单元」工作。运算单元收到要加和状态中的值的通知后就会把状态中的 1 和 2 读入并计算再将计算的结果 3 存放到状态中最后运算单元将结果返回给控制单元控制单元将结果传输给读写头读写头向右移动把结果 3 写入到纸带的格子中。可以发现图灵机的主要功能就是读取纸带格子中的内容交给控制单元识别字符是数字还是运算符指令如果是数字则存入到图灵机状态中如果是运算符则通知运算单元读取状态中的数值进行计算计算结果最终返回给读写头读写头把结果写入到纸带的格子中。事实上图灵机这个看起来很简单的工作方式和今天的计算机是基本一样的。冯诺依曼模型现代计算机的五大部件在 1945 年冯诺依曼和其他计算机科学家们提出了计算机具体实现的报告其遵循了图灵机的设计并提出用电子元件构造计算机同时约定了用二进制进行计算和存储。最重要的是它定义了计算机的基本结构为 5 个部分分别是运算器、控制器、存储器、输入设备、输出设备这 5 个部分也被称为冯诺依曼模型。运算器、控制器在中央处理器CPU里存储器就是我们常见的内存输入输出设备则是计算机外接的设备比如键盘是输入设备显示器是输出设备。存储单元和输入输出设备要与中央处理器打交道离不开总线。下面分别介绍内存、中央处理器、总线、输入输出设备。内存我们的程序和数据都存储在内存里存储的区域是线性的。在计算机数据存储中存储数据的基本单位是字节byte1 字节等于 8 位8 bit。每一个字节都对应一个内存地址。内存的地址从 0 开始编号然后自增排列最后一个地址为内存总字节数 - 1。这种结构好似程序里的数组所以内存读写任何一个数据的速度都是一样的。中央处理器CPU中央处理器也就是常说的 CPU32 位和 64 位 CPU 最主要区别在于一次能计算多少字节数据32 位 CPU 一次可以计算 4 个字节64 位 CPU 一次可以计算 8 个字节。这里的 32 位和 64 位通常称为 CPU 的位宽。之所以 CPU 要这样设计是为了能计算更大的数值如果是 8 位的 CPU那么一次只能计算 1 个字节0~255范围内的数值这样就无法一次完成计算10000 * 500。于是为了能一次计算大数的运算CPU 需要支持多个 byte 一起计算所以CPU 位宽越大可以计算的数值就越大比如 32 位 CPU 能计算的最大整数是4294967295。CPU 内部还有一些常见组件寄存器、控制单元和逻辑运算单元等。控制单元负责控制 CPU 工作逻辑运算单元负责计算而寄存器可以分为多种类每种寄存器的功能又不尽相同。为什么有了内存还需要寄存器原因很简单因为内存离 CPU 太远了而寄存器就在 CPU 里还紧挨着控制单元和逻辑运算单元自然计算时速度会很快。常见的寄存器种类通用寄存器用来存放需要进行运算的数据比如需要进行加和运算的两个数据程序计数器用来存储 CPU 要执行下一条指令「所在的内存地址」。注意它不是存储了下一条要执行的指令此时指令还在内存中程序计数器只是存储了下一条指令「的地址」指令寄存器用来存放当前正在执行的指令也就是指令本身。指令被执行完成之前指令都存储在这里。总线总线用于 CPU 和内存以及其他设备之间的通信可分为 3 种地址总线用于指定 CPU 将要操作的内存地址数据总线用于读写内存的数据控制总线用于发送和接收信号比如中断、设备复位等信号CPU 收到信号后自然进行响应这时也需要控制总线。当 CPU 要读写内存数据的时候一般需要通过下面这三个总线首先要通过「地址总线」来指定内存的地址然后通过「控制总线」控制是读或写命令最后通过「数据总线」来传输数据。输入、输出设备输入设备向计算机输入数据计算机经过计算后把数据输出给输出设备。期间如果输入设备是键盘按下按键时是需要和 CPU 进行交互的这时就需要用到控制总线了。线路位宽与 CPU 位宽数据是如何通过线路传输的呢其实是通过操作电压低电压表示 0高电压则表示 1。如果构造了「高低高」这样的信号其实就是 101 二进制数据十进制表示 5。如果只有一条线路就意味着每次只能传递 1 bit 的数据0 或 1那么传输 101 这个数据就需要 3 次才能传输完成效率非常低。这样一位一位传输的方式称为串行下一个 bit 必须等待上一个 bit 传输完成才能进行传输。当然想一次多传一些数据增加线路即可这时数据就可以并行传输。为了避免低效率的串行传输线路的位宽最好一次就能访问到所有的内存地址。CPU 要想操作内存地址就需要地址总线如果地址总线只有 1 条那每次只能表示「0 或 1」这两种地址所以 CPU 能操作的内存地址最大数量为 22^1个注意不要理解成同时能操作 2 个内存地址如果地址总线有 2 条那么能表示 00、01、10、11 这四种地址所以 CPU 能操作的内存地址最大数量为 42^2个。那么想要 CPU 操作 4G 大的内存就需要 32 条地址总线因为2^32 4G。CPU 位宽与线路位宽的匹配CPU 的位宽最好不要小于线路位宽比如 32 位 CPU 控制 40 位宽的地址总线和数据总线的话工作起来就会非常复杂且麻烦所以32 位的 CPU 最好和 32 位宽的线路搭配因为 32 位 CPU 一次最多只能操作 32 位宽的地址总线和数据总线。如果用 32 位 CPU 去加和两个 64 位大小的数字就需要把这 2 个 64 位的数字分成 2 个低位 32 位数字和 2 个高位 32 位数字来计算先加两个低位的 32 位数字算出进位然后加和两个高位的 32 位数字最后再加上进位就能算出结果。可以发现 32 位 CPU 并不能一次性计算出加和两个 64 位数字的结果。对于 64 位 CPU就可以一次性算出加和两个 64 位数字的结果因为 64 位 CPU 可以一次读入 64 位的数字并且 64 位 CPU 内部的逻辑运算单元也支持 64 位数字的计算。但是并不代表 64 位 CPU 性能比 32 位 CPU 高很多很少应用需要算超过 32 位的数字所以如果计算的数额不超过 32 位数字的情况下32 位和 64 位 CPU 之间没什么区别只有计算超过 32 位数字的情况下64 位的优势才能体现出来。另外32 位 CPU 最大只能操作 4GB 内存就算装了 8 GB 内存条也没用而 64 位 CPU 寻址范围则很大理论最大的寻址空间为2^64。程序执行的基本过程程序实际上是一条一条指令所以程序的运行过程就是把每一条指令一步一步地执行起来负责执行指令的就是 CPU。CPU 执行程序的过程如下第一步CPU 读取「程序计数器」的值这个值是指令的内存地址。然后 CPU 的「控制单元」操作「地址总线」指定需要访问的内存地址接着通知内存设备准备数据。数据准备好后通过「数据总线」将指令数据传给 CPUCPU 收到内存传来的数据后将这个指令数据存入到「指令寄存器」。第二步「程序计数器」的值自增表示指向下一条指令。这个自增的大小由 CPU 的位宽决定比如 32 位的 CPU指令是 4 个字节需要 4 个内存地址存放因此「程序计数器」的值会自增 4。第三步CPU 分析「指令寄存器」中的指令确定指令的类型和参数。如果是计算类型的指令就把指令交给「逻辑运算单元」运算如果是存储类型的指令则交由「控制单元」执行。简单总结就是一个程序执行的时候CPU 会根据程序计数器里的内存地址从内存里面把需要执行的指令读取到指令寄存器里面执行然后根据指令长度自增开始顺序读取下一条指令。CPU 从程序计数器读取指令、到执行、再到下一条指令这个过程会不断循环直到程序执行结束这个不断循环的过程被称为CPU 的指令周期。a 1 2 执行的具体过程CPU 是不认识a 1 2这个字符串的这些字符串只是方便我们程序员认识。要想这段程序能跑起来还需要把整个程序翻译成汇编语言的程序这个过程称为编译成汇编代码。针对汇编代码还需要用汇编器翻译成机器码这些机器码是由 0 和 1 组成的机器语言这一条条机器码就是一条条的计算机指令这才是 CPU 能够真正认识的东西。下面看看a 1 2在 32 位 CPU 上的执行过程。数据段与正文段程序编译过程中编译器通过分析代码发现 1 和 2 是数据于是程序运行时内存会有个专门的区域来存放这些数据这个区域就是「数据段」数据 1 被存放到 0x200 位置数据 2 被存放到 0x204 位置。注意数据和指令是分开区域存放的存放指令区域的地方称为「正文段」。编译器会把a 1 2翻译成 4 条指令存放到正文段中。这 4 条指令被存放到了 0x100 ~ 0x10c 的区域中0x100 的内容是load指令将 0x200 地址中的数据 1 装入到寄存器R00x104 的内容是load指令将 0x204 地址中的数据 2 装入到寄存器R10x108 的内容是add指令将寄存器R0和R1的数据相加并把结果存放到寄存器R20x10c 的内容是store指令将寄存器R2中的数据存回数据段中的 0x208 地址中这个地址也就是变量a内存中的地址。编译完成后具体执行程序的时候程序计数器会被设置为 0x100 地址然后依次执行这 4 条指令。上面的例子中由于是在 32 位 CPU 上执行的因此一条指令占 32 位大小所以你会发现每条指令间隔 4 个字节。而数据的大小是根据程序中指定的变量类型决定的比如int类型的数据占 4 个字节char类型的数据占 1 个字节。指令从汇编到机器码上面的例子中指令的内容写的是简易的汇编代码目的是为了方便理解指令的具体内容。事实上指令的内容是一串二进制数字的机器码每条指令都有对应的机器码CPU 通过解析机器码来知道指令的内容。不同的 CPU 有不同的指令集也就是对应着不同的汇编语言和不同的机器码。下面选用最简单的 MIPS 指令集来看看机器码是如何生成的这样也能明白二进制的机器码的具体含义。MIPS 的指令是一个 32 位的整数高 6 位代表着操作码表示这条指令是一条什么样的指令剩下的 26 位在不同指令类型下所表示的内容不同主要有三种类型R、I 和 J。R 指令用在算术和逻辑操作里面有读取和写入数据的寄存器地址。如果是逻辑位移操作后面还有位移操作的「位移量」而最后的「功能码」则是在前面的操作码不够时扩展操作码来表示对应的具体指令I 指令用在数据传输、条件分支等。这个类型的指令没有位移量和功能码也没有第三个寄存器而是把这三部分直接合并成了一个地址值或一个常数J 指令用在跳转高 6 位之外的 26 位都是一个跳转后的地址。将 add 指令翻译成机器码把前面例子中的这条指令「add指令将寄存器R0和R1的数据相加并把结果放入到R2」翻译成机器码。加和运算 add 指令属于 R 指令类型add 对应的 MIPS 指令里操作码是000000最末尾的功能码是100000这些数值都是固定的查一下 MIPS 指令集的手册就能知道rs代表第一个寄存器 R0 的编号即00000rt代表第二个寄存器 R1 的编号即00001rd代表目标的临时寄存器 R2 的编号即00010因为不是位移操作所以位移量是00000。把上面这些数字拼在一起就是一条 32 位的 MIPS 加法指令了用 16 进制表示的机器码则是0x00011020。编译器在编译程序的时候会构造指令这个过程叫做指令的编码CPU 执行程序的时候会解析指令这个过程叫作指令的解码。指令周期4 级流水线现代大多数 CPU 都使用流水线的方式来执行指令。所谓的流水线就是把一个任务拆分成多个小任务于是一条指令通常分为 4 个阶段称为 4 级流水线Fetch取得指令CPU 通过程序计数器读取对应内存地址的指令Decode指令译码CPU 对指令进行解码Execution执行指令CPU 执行指令Store数据回写CPU 将计算结果存回寄存器或者将寄存器的值存入内存。上面这 4 个阶段称为指令周期Instruction Cycle。CPU 的工作就是一个周期接着一个周期周而复始。事实上不同的阶段由计算机中的不同组件完成取指令阶段指令存放在存储器里。通过程序计数器和指令寄存器取出指令的过程是由控制器操作的指令的译码过程也是由控制器进行的指令执行的过程无论是进行算术操作、逻辑操作还是进行数据传输、条件分支操作都是由算术逻辑单元运算器处理的。但是如果是一个简单的无条件地址跳转则直接在控制器里面完成不需要用到运算器。指令的类型指令从功能角度划分可以分为 5 大类数据传输类型的指令比如store/load是寄存器与内存间数据传输的指令mov是将一个内存地址的数据移动到另一个内存地址的指令运算类型的指令比如加减乘除、位运算、比较大小等等它们最多只能处理两个寄存器中的数据跳转类型的指令通过修改程序计数器的值来达到跳转执行指令的过程比如编程中常见的if-else、switch-case、函数调用等信号类型的指令比如发生中断的指令trap闲置类型的指令比如指令nop执行后 CPU 会空转一个周期。指令的执行速度如何让程序跑得更快CPU 的硬件参数都会有GHz这个参数比如一个 1 GHz 的 CPU指的是时钟频率是 1 G代表着 1 秒会产生 1G 次数的脉冲信号。每一次脉冲信号高低电平的转换就是一个周期称为时钟周期。对于 CPU 来说在一个时钟周期内仅能完成一个最基本的动作。时钟频率越高时钟周期就越短工作速度也就越快。一个时钟周期一定能执行完一条指令吗答案是不一定的大多数指令不能在一个时钟周期完成通常需要若干个时钟周期。不同的指令需要的时钟周期是不同的加法和乘法都对应着一条 CPU 指令但是乘法需要的时钟周期就要比加法多。程序执行的时候耗费的 CPU 时间少就说明程序是快的。对于程序的 CPU 执行时间可以拆解成CPU 时钟周期数CPU Cycles与时钟周期时间Clock Cycle Time的乘积。时钟周期时间就是我们前面提及的 CPU 主频主频越高说明 CPU 的工作速度越快。比如一台 2.4 GHz 四核 Intel Core i5 电脑2.4 GHz 就是电脑的主频时钟周期时间就是 1/2.4G。要想 CPU 跑得更快自然是缩短时钟周期时间提升 CPU 主频。但是今非彼日摩尔定律早已失效当今的 CPU 主频已经很难再做到翻倍的效果了。换一个更好的 CPU这也是软件工程师控制不了的事情应该把目光放到另外一个乘法因子——CPU 时钟周期数。如果能减少程序所需的 CPU 时钟周期数量一样能提升程序的性能。对于 CPU 时钟周期数可以进一步拆解成「指令数 × 每条指令的平均时钟周期数Cycles Per Instruction简称 CPI」于是程序的 CPU 执行时间公式变为CPU 执行时间 指令数 × CPI × 时钟周期时间因此要想程序跑得更快优化这三者即可指令数表示执行程序所需要多少条指令以及哪些指令。这个层面基本靠编译器来优化毕竟同样的代码在不同的编译器下编译出来的计算机指令会有各种不同的表示方式每条指令的平均时钟周期数 CPI表示一条指令需要多少个时钟周期数。现代大多数 CPU 通过流水线技术Pipeline让一条指令需要的 CPU 时钟周期数尽可能少时钟周期时间表示计算机主频取决于计算机硬件。有的 CPU 支持超频技术打开超频意味着把 CPU 内部的时钟调快了于是 CPU 工作速度就变快了但是也有代价CPU 跑得越快散热的压力就越大CPU 会很容易崩溃。很多厂商为了跑分而跑分基本都是在这三个方面入手的特别是超频这一块。总结回答开头的几个问题64 位相比 32 位 CPU 的优势在哪主要体现在两个方面一次可计算的数字范围更大64 位 CPU 可以一次计算超过 32 位的数字而 32 位 CPU 如果要计算超过 32 位的数字要分多步骤进行计算效率就没那么高。但是大部分应用程序很少会计算那么大的数字所以只有运算大数字的时候64 位 CPU 的优势才能体现出来否则和 32 位 CPU 的计算性能相差不大可以寻址更大的内存空间32 位 CPU 最大的寻址地址是 4G即使加了 8G 大小的内存也还是只能寻址到 4G而 64 位 CPU 最大寻址地址是2^64远超于 32 位 CPU 的2^32。32 位/64 位软件与 32 位/64 位电脑能否互相兼容64 位和 32 位软件实际上代表指令是 64 位还是 32 位的如果 32 位指令在 64 位机器上执行需要一套兼容机制就可以做到兼容运行了。但是如果 64 位指令在 32 位机器上执行就比较困难了因为32 位的寄存器存不下 64 位的指令操作系统其实也是一种程序我们也会看到操作系统分为 32 位操作系统、64 位操作系统其代表意义就是操作系统中程序的指令是多少位。比如 64 位操作系统指令也就是 64 位的因此不能装在 32 位机器上。总之硬件的 64 位和 32 位指的是 CPU 的位宽软件的 64 位和 32 位指的是指令的位宽。延伸阅读本文属于 CS-Base 仓库《图解系统》硬件结构章节的开篇后续内容与该主题紧密衔接可在仓库中继续深入如何写出让 CPU 跑得更快的代码承接本文的「指令执行速度」小节讲解 CPU Cache 机制与数据/指令缓存命中率的提升方法是本文性能优化部分的直接延伸CPU 缓存一致性讲解写直达、写回机制与 MESI 协议回答多核缓存一致性问题CPU 是如何执行任务的讲解 CPU 如何读写数据、Cache 伪共享以及 CPU 调度任务的方式覆盖「硬件结构」章节的剩余主题磁盘比内存慢几万倍进一步展开存储器层次结构寄存器、CPU Cache、内存、SSD/HDD补充本文「冯诺依曼模型」中存储体系的宏观视角仓库入口可参考 图解系统介绍查看该系列文章的整体目录结构。赞分享文档教程知识库【免费下载链接】CS-Base图解计算机网络、操作系统、计算机组成、数据库共 1000 张图 50 万字破除晦涩难懂的计算机基础知识让天下没有难懂的八股文 在线阅读https://xiaolincoding.com项目地址https://gitcode.com/GitHub_Trending/cs/CS-Base点击查看免费下载相关推荐程序是如何运行的从双击图标到 CPU 执行指令的完整生命周期system-design-101 图解指南程序是如何运行的从双击图标到 CPU 执行指令的完整生命周期system design 101 图解指南 一个可执行文件静静躺在磁盘上当你双击它的那一刻后端文档教程easy-vibe 计算机组成原理精讲从冯·诺依曼架构到指令流水线easy vibe 计算机组成原理精讲从冯·诺依曼架构到指令流水线 本文是 Datawhale easy vibe 项目《计算机基础》附录系列的核心篇章承接教程文档Easy-Vibe 计算机组成原理精讲从冯诺依曼架构到指令流水线Easy Vibe 计算机组成原理精讲从冯诺依曼架构到指令流水线 导读 本文是 Easy Vibe https://link.gitcode.com/i/5教程文档上一篇Sunshine开源游戏串流服务器5步构建家庭游戏共享平台的完整指南下一篇LinkSwift网盘直链下载助手完整指南如何免费突破九大网盘下载限速创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考