在微处理器中,控制电路负责控制整个微处理器中所有部件的运行,控制的依据就是微处理器中正在执行的指令。指令即用来控制微处理器运行实现特定功能的二进制代码,是软件程序执行的最小单位。一般来讲,一条指令由指令的操作码和操作数两部分组成,操作码用来说明指令的功能和执行的操作,操作数则表明操作所涉及的源和目的数据的位置。在微处理器中,指令码被用于控制电路的指令译码,译码后的操作数将产生一系列的控制信号,以控制处理器的操作动作。
一个微处理器所支持的所有指令的集合被称作该微处理器的指令集。指令集一般被认为是计算机系统中软件与硬件的分界,也是一个微处理器系列最核心的特征之一。一个微处理器系列中的微处理器通常具有相同或相容的指令集,以实现软件的向下兼容。例如X86系列微处理器中,所有的微处理器,包括80386、Pentium、Core等的指令集都是8086指令集的超集,从而保证在8086上能够运行的程序,在这些新微处理器上也能够正常运行。
根据指令集设计的特点,微处理器的指令集可以被分成复杂指令集和精简指令集两种不同的设计模式。在早期的计算机业界,程序是以机器语言或汇编语言完成的。为了便于编写程序,计算机架构师设计出越来越复杂的指令,可以直接对应高级编程语言的高级功能。大容量内存的缺乏加速了这种复杂化。由于内存价格的高昂,内存中的每一字节都很宝贵,它使产业界倾向于高度编码的指令、长度不等的指令、多操作数的指令,以及把数据的搬移与计算合并在一起的指令。在当时看来,相对于使指令更容易解码,指令的编码打包等指令执行效率问题更为重要。同时,当时的内存使用的还是磁性技术,不仅容量少,而且速度很慢,凭借高密度打包的指令,访问慢速资源的频率可以降低。
除此之外,当时的集成电路技术水平使得在微处理器中设计大量寄存器对芯片或电路板而言是难以承受的。而且一旦具有大数量的寄存器,相关的指令字(操作码)将会需要更多的比特位(使用宝贵的RAM)来定位寄存器,这也不符合节省内存的要求。这就使得当时的微处理器中只能设计少量的寄存器。
基于上述原因,微处理器设计师尽可能使一条指令做更多的工作。这导致单个指令做全部的工作:读入两个加数,相加,并将计算结果直接写入内存;另一个例子是从内存读取两个数据,但计算结果存储在寄存器内;第三个例子是将从内存和寄存器各读取一个数据,其结果再次写入内存,以此类推。这种微处理器设计原理,被称为复杂指令集(Complex In-struction Set Computing,CISC)。X86系列微处理器就是典型的CISC微处理器。
20世纪70年代末到80年代,随着编译技术的不断成熟,软件设计不再依赖于复杂和功能强大的指令集,以高级语言编写程序,并由编译器将其编译为机器语言成为软件开发的常规手段。在代码生成时,编译器通常使用的是微处理器指令集中一个比较小而且比较简单的子集,其余的指令则很少被使用到。这时,复杂指令集指令数量多、指令执行效率较低的弱点就暴露了出来。
与此同时,微电子技术的进步使得存储器的容量得到了飞跃的增大,大容量的内存使得存储器效率不再是微处理器指令集设计的关键,指令易于解码变得比指令的编码打包更加重要。复杂指令集中指令长度不一、格式不一等带来的指令解码和并行处理上的难度成了提高微处理器性能的严重障碍,客观上要求微处理器的指令集向长度相等、格式相同的规整指令集演化。
除此之外,微处理器技术的进步也使得微处理器运行的速度和主存储器运行的速度逐渐拉开,高速运行的微处理器需要更多的寄存器来减少对运行速度较低的存储器的访问,支持微处理器的高速操作。为此,必须降低微处理器原本的复杂度,以节省出空间给新增的寄存器和缓存。
在这一系列因素的共同作用下,精简指令集技术(Reduced Instruction Set Computing,RISC)的出现也成为必然。使用精简指令集的微处理器系列主要有IBM的Power系列、Sun的SPARC系列、广泛使用在嵌入式领域的ARM系列等。这些RISC微处理器普遍比同等的CISC微处理器要快,而且设计和纠错也更加容易。但是精简指令集带来的是程序指令数量的膨胀,要完成相同的功能,RISC微处理器要从存储器读入并处理更多的指令,因此也带来了时间上的损失。(www.xing528.com)
从微处理器设计的角度来看,RISC和CISC的争论与竞争目前已经到了“融合”的阶段,适度复杂的指令集设计已经成为微处理器设计的共识。作为一个例子,虽然X86系列微处理器是一种典型的复杂指令集微处理器系列,但自从Intel Pentium Pro(P6)之后,X86系列的CPU也开始采用内核精简指令集,而在外围布置采用从复杂指令集到精简指令集(微操作)的译码电路动态译码方式,藉此提高CPU的性能,使作为复杂指令集CPU的X86系列微处理器也有可能在一个时钟周期内运行一条甚至多条指令。
微处理器执行一条指令一般需要经过至少四个步骤:取指、译码、执行和写回。首先,微处理器的控制器发出一系列的控制信号,根据程序计数器中存储的当前指令地址驱动总线接口部件从存储系统中取出即将被执行的指令,这个步骤被称作取指(Fetch)。然后,控制器将取到的指令依照指令的格式进行译码(Decode),由于不同指令集指令格式复杂程度差别甚大,其译码的难度也不相同。对于X86这样的复杂指令集微处理器,变长和不规整的指令集使得其指令译码难度要比RISC指令集的微处理器大得多,这也是性能相近的微处理器中X86系列微处理器需要使用更多的门电路实现的原因之一。
在指令被译码后,指令译码所得到的一系列控制信号将被用于控制微处理器中包括运算器、总线接口单元等在内的其他部件,以实现指令中所指定的功能。这个步骤被称作指令的执行步骤(Execution)。现代微处理器中经常设计有多个运算器等用于实现指令功能的处理部件,这些部件可以被并发驱动以执行一些可以被并行执行的指令,从而达到在一个时钟周期内执行多条指令,提高微处理器性能的目的。
在微处理器的指令集中,通常会有很多不同种类的指令,如算术逻辑运算指令、传送指令、转移指令、处理机控制指令等。指令的操作不同,其实现的复杂程度和执行所需的时间也不同。如8086微处理器中,类似CLC这样的处理机控制指令和寄存器之间的MOV指令,由于实现比较简单,只需要2个时钟周期即可完成。而乘法指令MUL/IMUL和除法指令DIV/IDIV的实现就要复杂得多,其执行需要的时间也更长,长达一百多个周期(例如16位带符号除法IDIV的执行需要最少190个时钟周期)。
实际上,这种不同指令在执行时间上的差别不仅仅来自于指令复杂程度上的不同,指令的执行通路能否得到充分的优化对于指令的执行速度也有着非常大的影响。由于指令数量较多,CISC微处理器通常很难针对其所有指令进行充分的优化,这也是CISC微处理器指令执行效率比较低的一个重要原因。Penitum Pro问世以来,X86系列微处理器采用了RISC内核,并以动态译码的方式将X86指令集的指令翻译成为RISC形式的微码,从而在一定程度上减轻了由于CISC指令集带来的对于处理器性能的影响。
指令的执行一般都要引起微处理器状态上的一些变化,比如修改微处理器状态寄存器内容、修改通用寄存器内容等,这些变化都在指令执行的“写回”步骤中真正得到执行。写回(Write-back)步骤又被称作“退休”或“退出”(Retirement),是一条指令执行的最后一步。在“写回”步骤没有得到执行之前,指令的处理结果被暂存在微处理器中的一系列暂存器之中,直到指令执行到写回步骤,这些结果才真正被用于改变处理机状态。
在早期的CISC微处理器中,指令种类多而且复杂,直接通过逻辑电路来实现所有的指令难度非常大,微处理器的设计者采用了一种被称作微程序的方式来实现CISC微处理器中的指令。每条机器指令被编写成一段微程序,每一个微程序包含若干条微指令,每一条微指令对应一条或多条微操作。在基于微程序的微处理器中,CPU内部有一个控制存储器,用于存放各种机器指令对应的微程序段。当CPU执行机器指令时,会在控制存储器里寻找与该机器指令对应的微程序,取出相应的微指令来控制执行各个微操作,从而完成该程序语句的功能。微程序设计克服了组合逻辑控制单元线路庞杂的缺点,同硬布线比较具有规整性,灵活性,可维护性等一系列优点。但是,增加了到控制存储器中读取微指令的时间导致基于微程序的微处理器指令执行速度慢,严重影响了系统的性能。在现代的RISC和RISC核心的微处理器中,指令的执行都采用硬连逻辑来实现。在这种微处理器中,所有的指令都由门电路互联形成的控制逻辑来解释和执行,而不再需要微程序。虽然硬连逻辑的实现增加了微处理器设计的难度,但由此带来的性能上的提升则使得硬连逻辑设计取代微程序成为当前微处理器设计的常用手段。在当前的X86系列微处理器中,指令视其复杂程度的不同被一组译码器件翻译成为一条或多条微操作(内核精简指令集),这些微操作再由硬连逻辑的控制器控制执行。这种近似于“实时编译”的手段,使得当前的X86系列微处理器能够在保持与早期的CISC微处理器指令集兼容的前提下,使用RISC的指令级并行技术,加快了指令的执行速度,提高了系统的整体性能。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。