构建C程序须要4个步骤,分别使用4个工具完成: preprocessor, compiler, assembler, and linker.四步完成后生成一个可执行文件。数据库
第一步,预处理. 这一步处理 头文件、条件编译指令和宏定义。编程
第二步,编译. 将第一步产生的文件连同其余源文件一块儿编译成汇编代码。数组
第三步,汇编。将第二步产生的汇编源码转换为 object file.编程语言
第四步,连接. 将第三步产生的一些object file 连接成一个可执行的文件。工具
【龙书】编译原理(第二版)学习与理解:性能
①编译器首先也是一种电脑程序。它会将用某种编程语言写成的源代码(原始语言),转换成另外一种编程语言(目标语言)。学习
②高级计算机语言便于人编写,阅读,维护。低阶机器语言是计算机能直接解读、运行的。编译器主要的目的是将便于人编写,阅读,维护的高级计算机语言所写做的源代码,翻译为计算机能解读、运行的低阶机器语言的程序。编译器将原始程序(Source program)做为输入,翻译产生使用目标语言(Target language)的等价程序。源代码通常为高阶语言 (High-level language), 如 Pascal、C、C++、C# 、Java 等,而目标语言则是汇编语言或目标机器的目标代码(Object code),有时也称做机器代码(Machine code)。优化
一开始看比较容易被各类词法,语法等弄得头大。其实计算机的所谓语法,类比一下天然语言,无非也同样是语言的结构方式。包括词的构成和变化, 词组和句子的组织。无外乎主谓宾这样的一些规则或者结构来表达一个意思。为了后续学习的顺利性,这里有必要先把各类术语搞清楚。spa
编译器的第一个步骤称为词法分析或扫描。它识别出一个个的单词(亦称单词符号或简称符号),如基本字(begin、end、if、for、while),标识符、常数、运算符和界符(标点符号、左右括号)。单词符号是语言的基本组成成分,是人们理解和编写程序的基本要素。识别和理解这些要素无疑也是翻译的基础。如同将英文翻译成中文的情形同样,若是你对英语单词不理解,那就谈不上进行正确的翻译。在词法分析阶段的工做中所依循的是语言的词法规则(或称构词规则)。描述词法规则的有效工具是正规式和有效自动机。翻译
词法分析器读入组成源程序的字符流,并将其组成有意义的词素的序列。形如<token-name, attribute-value>这样的词法单元。(token-name是由语法分析使用的抽象符号,attribute-value是指向符号表中关于这个词法单元的条目,符号表条目的信息会被语义分析和代码生成步骤使用)
例如源程序包含以下赋值语句:position = initial + rate * 60
对其进行词法分析:
抽象符号 |
词素 |
标识符 id | position |
赋值运算符 = | = |
标识符 id | initial |
加法运算符 + | + |
标识符 id | rate |
乘法运算符 * | * |
整数 60 | 60 |
空格(分析器直接忽略) |
通过词法分析以后,赋值语句的词法单元序列:<id, 1> < = > <id, 2> < + > <id, 3> < * > <60>
图1-1 一个赋值语句的翻译
① 语法是语言学的一个分支,研究按肯定用法来运用的词类、词的屈折变化或表示相互关系的其余手段以及词在句中的功能和关系。包含词的构词、构形的规则和组词成句的规则。
举个例子:我是人;他学习汉语;你登山...........这样的句子有千千万万。那么人们会总结出来:主语+谓语+宾语 这样的语法规则来。
因为计算机的特殊性,所以计算机的语法逻辑性更强,更注重算术和表达式等, 因此就没有那么简单的“主谓宾”,咱们看的更多的可能相似 x = y + 1,等;
② 文法:天然语言汉语中的意思1.法制;法规。 2.文章的做法。 3.语法。语言的结构方式。包括词的构成和变化﹐词组和句子的组织。文法即文章的书写法规,通常用来指以文字、词语、短句、句子的编排而组成的完整语句和文章的合理性组织。
文法即语言中的每一个句子能够用严格定义的规则来构造.
编译的第2个步骤称为语法分析或解析。语法分析器使用由词法分析器生成的各词法单元的第一个份量来建立树形的中间表示。该中间表示给出了词法分析产生的词法单元的语法结构。经常使用的表示方法是语法树,树中每一个内部节点表示一个运算,而该节点的子节点表示运算的份量。
以上赋值语句表示成语法树:
(数据的含义就是语义。简单的说,数据就是符号。数据自己没有任何意义,只有被赋予含义的数据才可以被使用,这时候数据就转化为了信息,而数据的含义就是语义)
语义分析器使用语法树和符号表中的信息来检查源程序是否和语言定义的语义一致 。它同时收集类型信息,并存放在语法树或符号表中,以便在中间代码生成过程使用。
语义分析的一个重要部分就是类型检查。好比不少语言要求数组下标必须为整数,若是使用浮点数做为下标,编译器就必须报错。再好比,不少语言容许某些类型转换,称为自动类型转换。
图1-1中显示了一个这样的自动类型转换,假设position,initial和rate已经被声明为浮点型,而词素60是一个整数。语义分析器输出中有一个inttofloat的额外节点,明确的把60转换为一个浮点数。
在进行了语法和语义的分析工做以后,编译程序将源程序变成了一种内部表示形式,这种内部表示形式叫作中间语言或中间代码, 也称为操做码(Operate Code,opcode)。Opcode cache的目地是避免重复编译,减小CPU和内存开销。(注: 若是动态内容的性能瓶颈不在于CPU和内存,而在于I/O操做,好比数据库查询带来的磁盘I/O开销,那么opcode cache的性能提高是很是有限的。可是既然opcode cache能带来CPU和内存开销的下降,这总归是好事。)
在源程序翻译成目标代码的过程当中,一个编译器可能构造出一个或多个中间表示。这些中间表示能够有多种形式。语法树是一种中间表示形式,它们一般在语法分析和语义分析中使用。
在源程序的语法分析和语义分析完成以后(也会生成中间表示,区别语法树),不少编译器生成一个明确的低级的或类机器语言的中间表示。该中间表示有两个重要的性质:1.易于生成;2.可以轻松地翻译为目标机器上的语言。
优化的任务在于对前段产生的中间代码进行加工变换,以期在最后阶段能产生出更为高效(省时间和空间)或能耗更低的目标代码。优化的主要方面有:公关子表达式的提取、循环优化、删除无用代码等等。有时,为了便于“并行运算”,还能够对代码进行并行化处理。优化所依循的原则是程序的等价变换规则。
代码生成以中间表示形式做为输入,并把它映射为目标语言。若是目标语言是机器代码,则必须为每一个变量选择寄存器或内存位置,中间指令则被翻译为可以完成相同任务的机器指令序列。
代码生成的一个相当重要的方面是合理分配寄存器以存放变量的值。