登录

编译器

百科 > 计算机 > 编译器

1.什么是编译器

  编译器是指从高级语言到低级语言的翻译器,同样的技术可用于不同种类语言之间的翻译。编译器是一种电脑程序,它会将用某种编程语言写成的源代码(原始语言),转换成另一种编程语言(目标语言)。

  它主要的目的是将便于人编写,阅读,维护的高级计算机语言所写作的源代码程序,翻译为计算机能解读、运行的低阶机器语言的程序,也就是可执行文件。编译器将原始程序(Source program)作为输入,翻译产生使用目标语言(Target language)的等价程序。源代码一般为高阶语言 (High-level language), 如 Pascal、C、C++、C# 、Java 等,而目标语言则是汇编语言或目标机器的目标代码Object code),有时也称作机器代码(Machine code)。

  一个现代编译器的主要工作流程如下: 源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 汇编程序 (assembler) → 目标代码 (object code) → 链接器 (Linker) → 可执行文件 (executables)

2.编译器的分类[1]

  典型的编译器输出是由包含人口点的名字和地址以及外部调用的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必须采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的可执行程序。

  在运行过程中,编译器又可分成只依赖于源语言的编译器前端和只依赖于目标语言的编译器后端两大部分,编译器前后端结构如图所示。

  Image:图编译器前后端示意图.jpg

  前端主要负责解析(parse)输入的源程序,由词法分析器和语法分析器协同工作。词法分析器负责把源程序中的“单词”(Token)找出来,语法分析器把这些分散的单词按预先定义好的语法组装成有意义的表达式、语句、函数等。例如“a=b+c”,前端词法分析器看到的是“'a'='b'+'c'”,语法分析器按定义的语法,先把它们组装成表达式“b+C”,再组装成“a=b+c”的语句。前端还负责语义(semantic checking)的检查,例如检测参与运算的变量是否是同一类型的,简单的错误处理。最终的结果常常是一个抽象的语法树AST(Abstract Syntax Tree),这样后端可以在此基础上进一步优化处理。编译器后端主要负责分析、优化中间代码以及生成机器代码。一般来说所有的编译器分析、优化、变型都可以分成两大类:函数内进行和函数间进行。很明显,函数间的分析优化更准确,但需要更长的时间来完成。

  一般编译器可以分为以下两类:

  ①“本地”编译器:编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的目标代码。

  ②交叉编译器:编译器也可以生成用来在其他平台上运行的目标代码,交叉编译器在生成新的硬件平台时非常有用。

  交叉编译这个概念的出现和流行是和嵌入式系统的广泛发展同步的。在进行嵌入式系统的开发时,运行程序的目标平台通常只有有限的存储空间和运算能力。例如常见的ARM平台,其一般的静态存储空问为16~32MB,而处理器的主频为100~500MHz。这种情况下,在ARM平台上进行本机编译就不太可能了,这是因为一般的编译工具需要很大的存储空间,并需要很强的处理器运算能力。为了解决这个问题,交叉编译工具就应运而生了。通过交叉编译工具,就可以在CPU能力很强、存储控件足够的主机平台上(例如通用计算机)编译出针对其他运行平台的可执行程序。

  在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码,这个编译过程就叫交叉编译。也就是在主机平台上开发程序,并在这个平台上运行交叉编译器,编译出程序,这个编译程序将在目标平台上运行。这里需要注意的是所谓平台,实际上包含两个概念:体系结构和操作系统。同一个体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行。举例来说,常说的X86Linux平台实际上是IntelX86体系结构和LinuxforX86操作系统的统称;而X86WinNT平台实际上是IntelX86体系结构和WindowsNTforX86操作系统的简称。

  在交叉编译技术中有两种比较典型的实现,一个称之为Java模式,即Java的字节码编译技术;另一个称之为GNUGCC模式,即通常所讲的CrossGCC技术。Java模式(如图所示)的最大特点是引入了一个自定义的虚拟机,即Java虚拟机JVM(Java Virtual Machine)。所有Java源程序都会首先被编译成只在这个虚拟机上才能执行的“目标代码”:字节码(Bytecode)。在实时运行时,可以有两种运行方式:一种是编译所获得的字节码由JVM在实际计算机系统上执行;另一种方式是通过Java实时编译器(Just-In-TimeCompiler)将字节码首先转换成本地机可直接执行的目标代码,而后交给实际的计算机系统运行。这实际上是一个两次编译过程,一次是非实时的,一次是实时的。由于第一次是非实时编译,Java编译器生成的是基于JVM的“目标代码”,可以将它的编译技术也称为交叉编译。

  Image:图Java模式交叉编译.jpg

  GCC模式(如图所示)通过CrossGCC直接生成目标平台的目标代码,从而能够直接在目标平台上运行。这里的关键是CrossGCC的生成和选择问题。需要根据目标平台的不同,选择针对这个平台的CrossGCC。GCC模式和Java模式的最大不同在于GCC直接生成目标平台的目标代码,而Java模式首先只是生成字节码,只有在有JIT编译器的参与下才会进一步生成目标平台的目标代码。研究表明,Java模式虽然可以通过两个编译过程生成目标代码,但是因为两次编译的优化存在相互冲突,最终的目标代码的执行效率也不是很高。而GCC模式由于直接能够生成目标代码,其执行效率一般很高。

  Image:图GCC模式交叉编译.jpg

评论  |   0条评论