人类之间的交流是通过语言进行的,但语言不是唯一的,不同的语言之间需要翻译,这就导致了翻译行业的建立。人与计算机之间也是通过语言进行交流的,但人类能理解的语言与机器能理解的语言是不同的,也需要翻译,这就导致了系列编译器的诞生。编译技术所讨论的问题,就是如何把符合人类思维方式的意愿(源程序)翻译成计算机能够理解和执行的形式(目标程序)。实现从源程序到目标程序转换的程序,称为编译程序或编译器。反编译技术所讨论的问题,就是如何把计算机能够理解和执行的形式(目标程序)翻译成便于人类理解的形式(高级语言源程序或流程图)。实现从目标程序到便于人类理解的系列文档的转换,称为反编译程序或反编译器。
编译器这个术语是由Grace Murray Hopper在20世纪50年代初期提出的,现代意义上最早的编译器是20世纪50年代后期的Fortran编译器,该编译器验证了经过编译的高级语言的生命力,也为后续高级语言和编译器的大量涌现奠定了基础。
反编译技术起源于20世纪60年代,比编译技术晚10年左右,但反编译技术的成熟度远不如编译技术。在半个世纪的发展过程中,出现了不少实验性的反编译器,其中以Dcc、Boomerang和IDA Pro的反编译插件Hex_rays最为著名。但这些反编译器都有这样或那样的缺陷。例如,Dcc只能识别最简单的数据类型;Boomerang无法识别复杂的数据结构,如C++的类和多维数组;Hex_rays只能产生可读性较低的C伪代码,且同样无法识别复杂的数据结构。因此,反编译技术还有很广阔的研究与发展空间。
本章仅对编译器和编译流程方面的知识进行概要阐述,反编译方面的概要介绍将在第10章给出。
1.1 编译器与解释器
计算机的硬件只能识别和理解由0、1字符串组成的机器指令序列,即目标程序或机器指令程序。在计算机刚刚发明的时期,人们只能向计算机输入机器指令程序来让它进行简单的计算。由于机器指令程序不易被人类理解,用它编写程序既困难又容易出错,于是就引入了代替0、1字符串的由助记符号表示的指令,即汇编指令,汇编指令的集合称为汇编语言,汇编指令序列称为汇编语言程序。但汇编程序实际上与机器语言程序是一一对应的,均要求程序员按照指令工作的方式来思考和解决问题,两者之间并无本质区别。因此,它们被称为面向机器的语言或低级语言。
随着计算机的发展和应用需求的增长,程序员的需求也大幅增长,但能够用机器语言或汇编语言编程的人员数量满足不了这种需求,许多科技工作者也想自己动手编写程序,因此,需要抽象度更高、功能更强的语言来作为程序设计语言,于是产生了面向各类应用的便于人类理解与运用的程序设计语言,即高级语言。尽管人类可以借助高级语言来编写程序,但计算机硬件真正能够识别和理解的语言还是由0、1组成的机器语言,这就需要在高级语言与机器语言之间建立桥梁,使得高级语言能够过渡到机器语言。也就是说,需要若干“翻译”,把各类高级语言翻译成机器语言。语言通常被分成三个层次:高级语言、汇编语言、机器语言。高级语言可以翻译成机器语言,也可以翻译成汇编语言,这两种翻译都称为编译。汇编语言到机器语言的翻译称为汇编。编译和汇编属于正向工程,有时还需要将机器语言翻译成汇编语言或高级语言,这通常称为反汇编或反编译,属于逆向工程。
在编译器工作方式下,源程序的翻译和翻译后程序的运行是两个相互独立的阶段。用户输入源程序,编译器对该源程序进行编译,生成目标程序,这个阶段称为编译阶段。目标程序在适当的输入下执行,最终得到运行结果的过程称为运行阶段。
解释器是另一种形式的翻译器。它把翻译和运行结合在一起进行,边翻译源程序,边执行翻译结果,这种工作方式被称为解释器工作方式。
换句话说,编译器的工作相当于翻译一本原著,原著相当于源程序,译著相当于目标程序,计算机的运行相当于阅读一本译著,这时,原著和翻译人员并不需要在场,译著是主角。解释器的工作相当于现场翻译,外宾和翻译都要在场,翻译边听外宾讲话,边翻译给听众,翻译是主角。解释器与编译器的主要区别是:运行目标程序时的控制权在解释器而不是目标程序。