第二章 编译和链接

2.1 被隐藏了的过程编译运行主要分解为4个步骤:预处理(Prepressing)、编译(Compilation)、汇编(Assembly)和(Linking).2.1.1 预编译预编译处理规则:1、  讲所有的“#define”删除,并且展开所有的宏定义。2、  处理所有条件预编译指令,比如“#if”、“#ifdef”、“#elif”、“#else”、“#endif”。3、  处理“#include”预编译指令,将包含的文件插入到该预编译指令的位置。注意,设个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。4、  删除所有的注释“//”和“/**/”.5、  添加行号和文件名标识,比如#2“hello.c” 2,以便于编译时编译器产生调试用的行号信息以及用于编译时产生编译错误或警告时能够显示行号。6、  保留所有的#pragma编译指令,因为编译器需要使用它们。 编译指令:$gcc –E hello.c –o hello.i或$cpp hello.c > hello.i 2.1.2编译编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件。编译指令:$gcc –s hello.i –o hello.s 2.1.3 汇编汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。编译指令:$as hello.s –o hello.o或者:$gcc –c hello.s –o hello.o或者:经过预编译,编译和汇编直接输出目标文件。$gcc –c hello.c –o hello.o 源码:后面都将以此为例Array[index] = (index + 4) * (2 + 6) 2.2 编译器做了什么编译过程分为6步:扫描语法分析语义分析源代码优化代码生成目标代码优化。如图2-2:  图2-2 编译过程2.2.1 词法分析将源代码程序输入到扫描器,扫描器进行词法分析,运用一种类似于有限状态机的算法可以很轻松的将源代码的字符序列分割成一系列的几号。词法分析产生的记号一般可以分为以下几类:关键字标识符字面量(数字、字符串)特殊符号(加号、等号等)。可使用工具:lex程序 2.2.2 语法分析语法分析器将扫描器产生的记号进行语法分析,从而产生语法树,整个分析过程采用了上下文无关法的分析手段,简单的讲,由语法分析器生成的语法树就是以表达式为节点的树。如图2-3: 语法分析工具:yacc  图2-3 语法树2.2.3 语义分析编译器所能分析的语义是静态语义静态语义是指在编译器可以确定的语义,与之对应的是动态语义,就是只能在运行期才能确定的语义。静态语义通常包括声明和类型的匹配、类型的转换。语义分析后结果如图2-4:  图 2-4 标识语义后的语法树2.2.4 中间语言生成源码级优化器:在源代码级别进行优化。如将(2+6)表达式优化掉。一般是将整个语法树转换成中间代码,它是语法树的顺序表示。如图2-5中间代码:接近目标代码,不同的编译器有不同的形式,常见的:三地址码P-代码。中间代码使得编译器可以分为前端和后端,编译器前端负责产生机器无关的中间代码,编译器后端将中间代码转换成目标机器代码。  图2-5 优化后的语法树2.2.5 目标代码生成与优化源代码级优化器产生中间代码标志着下面的过程都属于编译器后端,编译器后端主要包括:代码生成器目标代码优化器代码生成器:将中间代码转换成目标机器代码,依赖于目标机器。目标代码优化器:对目标代码进行优化,比如选择合适的寻址方式,使用位移来代替乘法运算、删除多余的指令等。至今没有一个编译器能够欧完整支持C++语言标准所规定的所有语言特性。 重定位:重新计算各个目标的地址过程符号:表示一个地址,这个地址可能是一个子程序(函数)的起始地址,也可以是一个变量的起始地址。最初程序是一个模块,后来功能越多,代码越来越多,复杂度增加,所以拆分为多个模块,在拆分为多个模块以后,这些模块之间最后如何组合形成一个单一的程序,模块之间如何组合的问题可以归结为模块之间如何通信,最常见的属于静态语言c/c++模块之间通信有两种方式:一种是模块间的函数调用,另一种是模块间的变量访问,函数访问须知道目标函数的地址,变量访问也须知道目标变量的地址,这两种方式都可以归结为一种:模块间的符号引用。:各个模块的拼接过程。 :每个源代码模块独立编译,然后按照需要将他们“组装”起来。:把各个模块之间相互引用的部分都处理好,使得各个模块之间能够正确的衔接。:地址和空间分配符号决议重定位.符号决议重定位 :一组目标文件的包,就是一些最常用的代码编译成目标文件后打包存放。运行时库:一种被编译器用来实现编程语言内置函数,以提供该语言程序运行时(执行)支持的一种特殊的计算机程序库 本章总结从程序源代码到最终可执行文件的4个步骤:预编译编译汇编,。C程序源代码转变成汇编代码的若干个步骤:词法分析语法分析语义分析中间代码生成目标代码生成与优化重定位符号符号决议目标文件运行库。 

相关内容推荐