现在的位置: 首页 > 综合 > 正文

读书笔记_编译过程

2012年11月06日 ⁄ 综合 ⁄ 共 2032字 ⁄ 字号 评论关闭

 

编译器的两个工作,一是基本的编译功能,一个是检查并报告被编译软件中的错误。先看程序的构建过程: 源程序经过编译器(Compiler)被编译为等价的汇编语言模块,再经过汇编器(Assembler)产生出与目标平台CPU一致的机器码模块,这些机器码模块虽然已经可以被目标CPU所执行,但其中可能还包含没有解决(unresolved)的名称和地址引用,因此需要连接器(Linker)解决这些问题,并产生出符合目标平台上的操作系统所要求的可执行模块。当用户执行程序时,操作系统的加载器(loader)会解读连接器记录在可执行模块中的格式信息,将程序中的代码和数据“布置”在内存中,成为真正可以运行的内存映像。

所以程序的构建过程可以简单归结为

源码——编译——汇编——链接——加载内存——执行。

下面具体看链接器。连接器的主要职责是将编译器产生的多个目标文件合成为一个可以在目标平台下执行的执行映像。目标平台是指程序的运行环境,包括CPU和操作系统。例如,如果我们要在Windows操作系统下运行的应用程序,那么连接器应该根据windows操作系统定义的可执行文件格式来产生可执行文件,也就是产生PE (portable Executable)格式的执行映像文件,产生PE格式的可执行文件,连接器要完成的任务:

解决目标文件中的外部符号,包括函数调用和变量引用。如果调用的函数是Windows API或其他位于DLL模块中的函数,那么必须为这些调用建立输入目录表(Import Directory Table)和输入地址表(import Address Table, IAT)。输入目录表用来描述被引用的文件,IAT表用来记录或重定位被引用函数的地址。连接器会把输入目录表和IAT表放在PE文件的输入数据段(.idata)中。

生成代码段(.text),放入已经解决了外部引用的目标代码

生成包含只读数据的数据段(.data).

生成包含资源数据的资源段(.rsrc)

生成包含基地址重定位表(Base Relocation Table)的.reloc段。当链接器产生PE文件时,它会假定一个地址作为本模块的基地址,比如VC6编译器为EXE模块定义的默认基地址是0x00400000。当程序运行时,如果加载器将一个模块加载到与默认值不同的基地址,那么这时就需要用重定位表进行重定位,可以通过连接器的链接选项来指定模块的默认基地址,也可以使用Visual studio 所附带的Rebase工具来修改DLL文件的默认地址。

如果定义了输出函数和变量,则产生包含输出表的.edata段。输出表通常出现在DLL文件中,EXE文件一般不包含.edata段,但NTOSKRNL.exe是个例外。

生成PE文件头,文件头描述了文件的构成和程序的基本信息。

 

下面介绍加载器(Loader)

加载器是操作系统的一个部分,它负责将可执行程序从外部存储器(硬盘)加载到内存中,并做好执行准备,包括遍历输入目录表加载依赖模块,遍历IAT表绑定动态调用的函数,对基地址发生冲突的模块执行调整工作等。NTDLL中包含了一系列以Ldr开头的函数,用于完成以上任务。

 下面来看编译过程

编译器的基本功能是将一种语言编写的程序(源程序)翻译成用另一种语言表示的等价程序(目标),一般是从高层次的语言翻译到低层次的语言。

主要包括两部分,前端主要负责理解源代码的含义,即分析(analysis)功能,后端负责产生等价的目标程序,即合成(synthesis)功能。

前端和后端之间的媒介是中间代码,又称为中间表示(Intermediate Representation),即IR。编译器前端对源程序进行词法分析,语法分析,语义分析,并将其映射到中间表示,后端对中间表示进行优化处理,再将其映射到用机器码表示的目标程序中。然后,链接器再将目标程序经链接称为可以执行的执行映像。

词法分析,语法分析,语义分析之间的区别:

词法分析(Lexical Analysis): 负责读取并扫描源程序文件的字符流,剔除其中的空格和注释内容,并根据构词规则识别出单词,将源代码中的字符流转化成记号流(token stream)。实现该功能的部分通常被称为扫描器(scanner)。

语法分析(Syntax Analysis): 对词法分析产生的记号流进行层次分析,根据语法规则(syntax rules)把单词序列组成语法短语,并表示为语法树(syntax tree)或推导树(derivation tree)的形式。

语义分析(Semantic Analysis):对语法树中的语句进行语义处理,审查数据类型的正确性,以及运算符使用是否符合语言规范。因为编译阶段的语义分析无法分析程序运行时才确定的动态语义,所以编译时的语义分析又称为静态语义分析(static semantic analysis),简称SSA。

所以编译过程的6个主要步骤为: 词法分析,语法分析,语义分析,中间代码生成,优化和目标代码生成。

抱歉!评论已关闭.