您的位置:首页 > 其它

解释执行和编译执行的区别、基于栈和基于寄存器的指令集区别

2017-05-22 15:10 405 查看

1. 解释执行和编译执行的区别

我们在学习java的时候,对class文件都有个疑惑,虚拟机是如何执行发方法中的字节码指令的呢?其实 虚拟机的执行引擎在执行java代码的时候有解释执行和编译执行两种选择。通俗说来,解释执行是通过解释器执行,编译执行即通过即时编译器产生本地代码执行。

开始前,先了解下大部分的程序代码到物理机的目标代码或虚拟机的指令集之前,要经过下图步骤, 先看图:



此图下面一条路径就是传统编译原理中程序代码到目标代码的生成过程。而中间的分支就是解释执行的过程。一般的虚拟机语言都会基于现代经典编译原理的思路实现,在执行前先对程序源码进行词法分析,这个阶段的任务是从左到右一个字符一个字符地读入源程序,对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号,如标识符、常数、运算符、定界符等),获取单词流。而后进行语法分析,它的作用是从输入中分析出其结构并将其转换为在后续处理过程中更易于访问的数据结构(一般是树类的数据结构),并检测可能存在的语法错误。经过词法分析和语法分析后源码被转换成抽象语法树(Abstract Syntax Tree,AST)。对于具体的语言实现来说,词法分析、语法分析和后面的优化器以及目标代码生成器都可选择独立的执行引擎,形成一个完整意义的编译器去实现,比如C/C++;也可以选择把其中的一部分步骤(如生成抽象语法树之前)实现为一个半独立的编译器,比如Java;又或者把这些步骤和执行引擎全部集中封装在一个封闭黑匣子中,如大多数JavaScript执行器。

java语言中,javac编译器完成源码的词法分析、语法分析到抽象语法树,再便利语法树生成线性字节码指令流。这一部分是在java虚拟机之外进行的,而解释器在虚拟机内部,因此java程序的编译是半独立的。

1.1 解释执行

解释执行是高级语言翻译程序的一种,它将源语言编写的源程序作为输入,解释一句就提交给计算机执行一句,并不形成目标程序。例如翻译领域的“口译”一样。

优点:方便快捷,适合小型机计算;不依赖于平台;

缺点:解释程序执行缓慢,效率低下,如源程序有循环时,计算机资源大量浪费。

1.2 编译执行

编译执行把高级语言源程序作为输入,进行翻译转换产出机器语言的目标程序,让计算机直接执行目标程序的到计算结果。

优点:编译完成后可多次使用,生成的可执行文件效率高,占用资源少,适用于复杂的程序。

缺点:兼容性差,编译过程需要很多时间开销。

现在很多语言使用二者结合方式,如Java、Python等。

2. 基于栈和基于寄存器的指令集区别

上面说了java是解释执行和编译执行相结合的,那么对于java编译器输出的字节流,java是如何执行的呢?其基本是一种基于栈的指令集架构,指令流中的指令大部分是零地址指令,它们依赖操作数栈进行工作。而基于寄存器的指令集(主流pc直接支持的指令集架构)依赖于寄存器进行工作。

举个例子:当我们计算1+1的时候,

基于栈的指令集会是这样:

iconst_1
iconst_1 //两条iconst_1指令连续把两个常量1压入栈
iadd     //iadd指令把栈顶的两个值出栈、相加后把结果放回栈顶。
istore_0 //把栈顶值存入局部变量表第0个slot中


基于寄存器的指令是这样:

mov eax,1   //将eax寄存器址设为1
add eax,1   //将eax寄存器与1相加结果依旧存入eax寄存器


我们不难得出:

1.基于栈的指令集

优点:可移植(寄存器由硬件提供,程序依赖硬件寄存器会收到硬件约束),基于栈的指令集架构,用户不会直接使用这些寄存器,由虚拟机实现决定把一些访问频繁的数据放到寄存器中获得尽量更好的性能;还有优点是代码相对紧凑(字节码中每个字节对应一条指令)、编译器实现简单(无需考虑空间分配)等;

缺点:执行速度慢,效率较低。因为操作本身伴随着大量的入栈出栈,导致完成相同功能所需的指令数量增加;更重要的是栈实现在内存中,频繁的栈访问意味着频繁的内存访问,这大大降低了效率。

2.基于寄存器的指令集

优点:效率相对较高

缺点:平台依赖,可移植性差。编译实现复杂。(相对于基于栈来说)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: