CPU执行的也不只是一条指令,一般一个程序包含很多条指令
因为有if…else、for这样的条件和循环存在,这些指令也不会一路平直执行下去。
一个计算机程序是怎么被分解成一条条指令来执行的呢
1 CPU如何执行指令
CPU里差不多几百亿个晶体管
实际上,一条条计算机指令执行起来非常复杂
好在CPU在软件层面已经为我们做好了封装
对于程序员来说,我们只要知道,写好的代码变成了指令之后,是一条一条顺序执行
不管几百亿的晶体管的背后是怎么通过电路运转起来的
逻辑上,我们可以认为,CPU其实就是由一堆寄存器组成的
而寄存器就是CPU内部,由多个触发器(Flip-Flop)或者锁存器(Latches)组成的简单电路。
触发器和锁存器,其实就是两种不同原理的数字电路组成的逻辑门
如果想要深入学习的话,可以学习数字电路的相关课程
N个触发器或者锁存器,就可以组成一个N位(Bit)的寄存器,能够保存N位的数据
比方说,我们用的64位Intel服务器,寄存器就是64位的
CPU里有很多种不同功能的
1.1 寄存器
寄存器(Register),是*处理器内的其中组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。在*处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器。在*处理器的算术及逻辑部件中,包含的寄存器有累加器。
在计算机体系结构里,处理器中的寄存器是少量且速度快的计算机存储器,借由提供快速共同地访问数值来加速计算机程序的运行:典型地说就是在已知时间点所作的之计算中间的数值。
寄存器是存储器层次结构中的最顶端,也是系统操作数据的最快速途径。寄存器通常都是以他们可以保存的比特数量来估量,举例来说,一个8位寄存器或32位寄存器。寄存器现在都以寄存器数组的方式来实现,但是他们也可能使用单独的触发器、高速的核心存储器、薄膜存储器以及在数种机器上的其他方式来实现出来。
这个名词通常都用来意指由一个指令之输出或输入可以直接索引到的寄存器组群。更适当的是称他们为“架构寄存器”。例如,x86指令集定义八个32位寄存器的集合,但一个实现x86指令集的CPU可以包含比八个更多的寄存器。
1.1.1 PC寄存器(Program Counter Register)
亦称指令地址寄存器(Instruction Address Register)
存放下一条需要执行的计算机指令的内存地址
1.1.2 指令寄存器(Instruction Register)
存放当前正在执行的指令
1.1.3 条件码寄存器(Status Register)
用里面的一个一个标记位(Flag),存放CPU进行算术或者逻辑计算的结果
CPU里面还有更多用来存储数据和内存地址的寄存器
这样的寄存器通常一类里面不止一个
通常根据存放的数据内容来给它们取名字,比如
常量寄存器
用来持有只读的数值(例如0、1、圆周率等等)。由于“其中的值不可更改”这一特殊性质,这些寄存器未必会有实体的硬件电路相对应,例如将从零常数寄存器读的操作实现为接通目标寄存器的下拉电阻。
一般而言,即使真正在硬件中放置常数寄存器也未必会是出于体系结构理论上的考虑,而很可能是由硬件描述语言为了简化操作而自动生成的电路
整数寄存器
用来存储整数数字(参考以下的浮点寄存器)。在某些简单(或旧)的CPU,特别的数据
寄存器是累加器,作为数学计算之用。
浮点数寄存器(FPRs)
用来存储浮点数字。
向量寄存器
用来存储由向量处理器运行SIMD指令所得到的数据。
地址寄存器
持有存储器地址,以及用来访问存储器。在某些简单/旧的CPU里,特别的地址寄存器是索引寄存器(可能出现一个或多个)。
有些寄存器既可以存放数据,又能存放地址,我们就叫它通用寄存器(GPRs)。
程序执行的时候,CPU会
- 根据PC寄存器里的地址
- 从内存里面把需要执行的指令读取到指令寄存器里面执行
- 然后根据指令长度自增
- 开始顺序读取下一条指令
可以看到,一个程序的一条条指令,在内存里是连续保存的,也会一条条顺序加载
而有些特殊指令,比如上一讲我们讲到J类指令,也就是跳转指令,会修改PC寄存器里面的地址值
这样,下一条要执行的指令就不是从内存里面顺序加载的了
事实上,这些跳转指令的存在,也是我们可以在写程序的时候,使用
- if…else条件语句
- while/for循环语句
的原因