(低级语言 || 高级语言) && (编译 || 解释)
一、低级语言与高级语言
最初的计算机程序都是用0和1的序列表示的,程序员直接使用的是机器指令,无需翻译,从纸带打孔输入即可执行得到结果。后来为了方便记忆,就将用0、1序列表示的机器指令都用符号助记,这些与机器指令一一对应的助记符就成了汇编指令,从而诞生了汇编语言。无论是机器指令还是汇编指令都是面向机器的,统称为低级语言。因为是针对特定机器的机器指令的助记符,所以汇编语言是无法独立于机器(特定的CPU体系结构)的。但汇编语言也是要经过翻译成机器指令才能执行的,所以也有将运行在一种机器上的汇编语言翻译成运行在另一种机器上的机器指令的方法,那就是交叉汇编技术。
高级语言是从人类的逻辑思维角度出发的计算机语言,抽象程度大大提高,需要经过编译成特定机器上的目标代码才能执行,一条高级语言的语句往往需要若干条机器指令来完成。高级语言独立于机器的特性是靠编译器为不同机器生成不同的目标代码(或机器指令)来实现的。那具体的说,要将高级语言编译到什么程度呢,这又跟编译的技术有关了,既可以编译成直接可执行的目标代码,也可以编译成一种中间表示,然后拿到不同的机器和系统上去执行,这种情况通常又需要支撑环境,比如解释器或虚拟机的支持,Java程序编译成bytecode,再由不同平台上的虚拟机执行就是很好的例子。所以,说高级语言不依赖于机器,是指在不同的机器或平台上高级语言的程序本身不变,而通过编译器编译得到的目标代码去适应不同的机器。从这个意义上来说,通过交叉汇编,一些汇编程序也可以获得不同机器之间的可移植性,但这种途径获得的移植性远远不如高级语言来的方便和实用性大。
二、编译与解释
编译是将源程序翻译成可执行的目标代码,翻译与执行是分开的;而解释是对源程序的翻译与执行一次性完成,不生成可存储的目标代码。这只是表象,二者背后的最大区别是:对解释执行而言,程序运行时的控制权在解释器而不在用户程序;对编译执行而言,运行时的控制权在用户程序。
解释具有良好的动态特性和可移植性,比如在解释执行时可以动态改变变量的类型、对程序进行修改以及在程序中插入良好的调试诊断信息等,而将解释器移植到不同的系统上,则程序不用改动就可以在移植了解释器的系统上运行。同时解释器也有很大的缺点,比如执行效率低,占用空间大,因为不仅要给用户程序分配空间,解释器本身也占用了宝贵的系统资源。
呵呵,这些东西随便找一本编译原理的书就有介绍,要想成为一个好的程序员,应该多了解一点编译的知识,不一定精通,但概念应该清楚。
解释、编译与反编译
从cpu到操作系统
cpu能够执行的是二进制表示的指令,确切的说是基本指令。然后cpu中有一些微代码,然后就把一些非基本指令也作为指令一样能够用了,而cpu内部会对这些复杂的指令进行解释。而操作系统架在硬件之上,又提供了一些服务和操作。最常见的是对于磁盘文件,或者进程线程这些东西的支持。其实是又一次扩展了你能够使用的功能,但是又限制了一些你的权限,比如你不能直接指定地址的进行写入之类的。而你对于一个磁盘文件读写功能的调用,表现出来可能是用unix中的某些强大的系统提供的小工具,然后利用进程间通信的管道之类的东西得到输出。也可能是利用win32中的一些系统提供的dll,利用里面的c的函数提供的一些api。还又可能是你直接用汇编调用中断,直接让操作系统处理中断得到结果。可以看到,从系统小工具,到api到系统中断,之间都有封装。而封装其实是一种解释,也就是你调用的是一些比如是ReadFile的api,然后这个操作并不是静态的成为二进制代码在编译期就成为指令一类的东西,而是在运行的时候由操作系统来解释,从而执行。所以说常用的封装其实是一种解释执行的办法。当然,就是连系统中断其实都要认为是解释了,按照这样的说法。
从源代码到可执行文件
另一个要注意解释的是运行在操作系统上的二进制表达的可执行文件和字符表达的源代码之间。这个是最常见的解释和编译进行辨析的地方。从汇编源代码到可执行文件是非常著名的编译了,是的的却却的编译。c的源代码也是。c++的也是,不过c++的某些东西就不完全是了,比如异常的处理。可以看到是需要运行时支持的功能都是不能完全静态翻译的,需要动态的解释。而最早的basic就是纯粹的解释执行了,你输入源代码然后解释器一行一行的读,然后给出输出。
在编译和解释之间玩平衡
最好玩的是在解释和编译直接玩平衡。python和java这些都是。他们在解释之前进行了一定的编译,比如java把源代码变成byte code的.class文件,python也有类似的pyc文件,其实也就是能够在运行的时候省去了语法和结构的分析,直接执行的是一种中间的语言。其实是把解释分成了编译和解释两部分。编译的结果是另外一种语言,而解释的就是那种中间语言了。只是中间语言比纯粹人类都能够看懂的源代码更加适合运行时快速的解释执行。但是java在真正解释的时候又弄了一些小花招,那就是所谓的just in time的技术。它预先读取一些byte code表示的代码,然后在你执行到那儿之前把那些byte code翻译成为本地的机器码,
从而使得真正执行到的时候速度很快。奥妙就在于预先读取和预先编译。这个是真正有新意的把解释和编译进行融合的做法。而使用的技术和cpu的缓存优化技术很像。甚至受到这个启发,我们还能够把cpu中的pipeline和数据指令双缓存的技术给用到对于解释语言的解释执行之中。
总之,解释和编译其实都非常有用。而且大家平时并没有注意到很多东西都非别是什么。