从上图中咱们看到CPU内部有3个首要组成部分:指令寄存器,指令译码器,指令履行单元(包含ALU和通用寄存器组)。
CPU在履行1条指令的时分,首要有3个过程:取指(将指令从内存或指令cache中取入指令寄存器);译码(指令译码器对指令寄存器中的指令进行译码操作,然后辨识出该指令是要履行add,或是sub,或是其它操作,然后发生各种时序操控信号);履行(指令履行单元依据译码的成果进行运算并保存成果)
现在咱们假定一下:CPU串行履行程序(即:履行完1条指令后,再履行下一条指令);指令履行的3个过程中每个过程都耗时1秒;整个程序共10条指令。那么,这个程序总的履行时间是多少呢?明显,是30秒。但这个成果令咱们十分不满意,由于它太慢了。有没有方法让它座上京津高铁提速3倍呢?当然有!仔细观察上图,咱们发现:取指阶段占用的CPU硬件是指令通路和指令寄存器;译码阶段占用的CPU硬件是指令译码器;履行阶段占用的CPU硬件是指令履行单元和数据通路。三者占用的CPU硬件彻底不同,这样就使得如下的操作得以进行:在对第1条指令进行译码的时分,能够一起对第2条指令进行取指操作;在对第1条指令进行履行的时分,能够一起对第2条指令进行译码操作,对第3条指令进行取指操作。明显,这样就能够将该程序的运转总时间从30秒缩减为12秒,提速近3倍。上面所述并行运转指令的方法就被称为流水线操作。可见:流水线操作的实质是运用指令运转的不同阶段运用的CPU硬件互不相同,并发的运转多条指令,然后进步时间功率。
流水线的引进,确实进步了CPU运转指令的时间功率,但却为咱们的汇编程序编写引进了新的问题。请看下面的剖析:
寄存器PC的值是即将被取指的指令的地址,正常状况下,在该条指令被取入CPU后履行期间,PC的值坚持不变,在该条指令履行完结的时间点上,硬件会主动将PC的值添加一个单位的巨细,这样PC就指向了下一条将被取指和履行的指令。而在引进流水线后,PC值的状况发生了改变,假定第1条指令的内存地址为X,则在时间T,PC的值变为X,并在时间T至时间T+1期间保持不变;在时间T+1,PC的值变为X+1个单位,并在时间T+1至时间T+2期间保持不变;在时间T+2,PC的值变为X+2个单位,并在时间T+2至时间T+3期间保持不变;在时间T+3,PC的值将变为X+3个单位。由此可见,在第1条指令的履行阶段,PC的值不再是该指令在内存中的方位,而是该指令在内存中的方位+2个单元。关于ARM指令集而言,每条指令的长度为32bit,占4byte,所以1条指令在内存中需求4byte存储。因而,咱们的定论是:
指令履行时,PC的值 = 当时正在履行指令在内存中的地址 + 8
请紧记以上定论。尽管现在咱们并不了解这个定论有何效果,但在后续的课程中,特别是经过检查反汇编代码的方法了解伪指令和编译器行为的时分,这个定论将会很有协助。
最终阐明一点:其实ARM现在的CPU的流水线级数早已经突破了3级。但我依然以3级流水线来进行解说,是由于:1、较之多级流水线,3级流水线最简略,因而也最便于初学者了解;2、尽管存在多种等级的流水线,但ARM出于统一和前后兼容的考虑,PC的值 = 当时正在履行指令在内存中的地址 + 8这个定论在所有的流水线等级上都是相同的。作为编程人员而言,咱们只需求知道这个定论即可。
称谢:感谢安博中程的Michael Tang为本文制作了示意图。