基于栈的指令集与基于寄存器的指令集

java编译器输出的指令流,基本上是一种基于栈的指令集架构(Instruction Set Architecture, ISA),指令流中的指令大部分都是零地址指令,它们依赖操做数栈进行工做。与之相对的另一套经常使用的指令集架构是基于寄存器的指令集,最典型的就是x86的二地址指令集,说的通俗些,就是如今咱们主流PC机中直接支持的指令集架构,这些指令依赖寄存器进行工做。那么,基于栈的指令集与基于寄存器的指令集这二者之间有什么不一样呢?
举个最简单的例子,分别使用这两种指令集计数“1+1”的结果,基于栈的指令集会是这样子的:
iconst_1
iconst_1
iadd
istore_0
两条iconst_1指令连续把两个常量1压入栈后,iadd指令把栈顶的两个值出栈,相加,而后把结果放回栈顶,最后istore_0把栈顶的值放入到局部变量表的第0个Slot中。
若是基于寄存器,那程序可能会是这样子:
mov eax, 1
add eax, 1
mov指令把EAX寄存器的值设为1,而后add指令再把这个值加1,结果就保存在EAX寄存器里面。
了解了基于栈的指令集与基于寄存器的指令集的区别后,也许可能还有疑问,这两套指令集谁会更好一些呢?
应该这么说,既然两套指令集会同时并存和发展,那确定是各有优点的,若是有一套指令集全面优于另外一套的话,就不会存在选择的问题了。
基于栈的指令集主要的优势就是可移植,寄存器由硬件直接提供,程序直接依赖这些硬件寄存器则不可避免地要受到硬件的约束。列如,如今32位80x86体系的处理器中提供了8个32位的寄存器,而ARM体系的CPU(在当前的手机,PDA中至关流行的一种处理器)则提供了16个32位的通用寄存器。若是使用栈架构的指令集,用户程序不会直接使用这些寄存器,就能够由虚拟机实现来自决定把一些访问最频繁的数据(程序计数器,栈顶缓存等)放到寄存器中以获取尽可能好的性能,这样实现起来也更加简单些。栈架构的指令集还有一些其余的优势,如代码相对更加紧凑(字节码中每一个字节就对应一条指令,而多地址指令集中还须要存放参数),编译器实现更加简单(不须要考虑空间分配的问题,所需空间都在栈上操做)等。
栈架构指令集的主要缺点是执行速度相对来讲会稍慢些。全部主流物理机的指令集都是寄存器架构也从侧面印证了这一点。
虽然栈架构指令集的代码很是紧凑,可是完成相同功能的指令数量通常会比寄存器架构多,由于出栈,入栈操做自己就产生了至关多的指令数量。更重要的是,栈实如今内存之中,频繁的栈访问也就意味着频繁的内存访问,相对于处理器来讲,内存始终是执行速度的瓶颈。尽管虚拟机能够采起栈顶缓存的手段,把最经常使用的操做映射到寄存器中避免直接内存访问,但这也只能是优化措施而不是解决本质问题的方法,因为指令数量和内存访问的缘由,因此致使了栈架构指令集的执行速度会相对较慢。java