高级语言转换为可执行语言的过程(以gcc编译器为例).源文件为hello.c
步骤一:预处理。将源文件hello.c预处理成hello.i。该步是将#include中包含的头文件导入到源文件中。命令是gcc -E hello.c
步骤二:编译。将预处理后的hello.i文件编译成hello.s文件。该步是将高级语言转换为汇编语言。命令是gcc -S hello.i步骤二为编译原理的过程
步骤三:汇编。将编译后的hello.s文件会变成hello.o文件。该步是将汇编语言转换成二进制文件。命令是gcc -c hello.s
步骤四:链接。将汇编后的hello.c文件链接为hello.exe文件,该步是将二进制文件装入动态库如编译器自带的print函数等。命令是gcc hello.o
而编译程序是等价地将高级语言程序转换为低级语言程序(如汇编语言或机器语言程序)的程序。即对应上述的步骤二编译过程
编译程序的分类
编译程序分为诊断编译程序,优化编译程序,交叉编译程序,可变目标编译程序四类
1.诊断编译程序:其作用是发现程序的错误,进行调试
2.优化编译程序:其作用是提高目标代码的程序效率
3.交叉编译程序:编译程序产生不同于宿主机(运行源程序的机器)的机器目标代码(目标机),则称为交叉编译程序
4.可变目标编译程序:仅编译和目标机器有关的部分的程序
解释程序和编译程序的区别
解释程序是将源程序作为输入,边解释边执行,不会产生完整的目标程序。而编译程序会先进行编译,产生一个目标程序,然后执行该目标程序从而得到结果。
解释程序的过程示意图:

优点:可移植性较好,只要有解释环境,可在不同的操作系统上运行。
缺点:运行需要解释环境,运行起来比编译慢,占用资源也要多一些,代码效率低,代码修改后就可运行,不需要编译过程。
编译程序的过程示意图:

优点:运行速度快,代码效率高,编译后的程序不可修改,保密性较好。
缺点:代码需要经过编译才能运行,可移植性差,只能在兼容的操作系统上运行。
编译程序的工作过程
程序编译共经过5个阶段
第一阶段:词法分析
根据构词规则,对输入程序的字符串进行扫描和分解,识别出单词字符。利用有限自动机法描述
第二阶段:语法分析
在词法分析的基础上,根据语法规则将单词符号串分解成各类语法单位、用上下文无关文法描述
第三阶段:中间代码产生
对各类语法单词按照语义进行翻译。该阶段需要进行静态语义检查,用属性文法描述。不会产生目标代码
第四阶段:优化
根据程序的等价变换规则对中间代码进行加工变换,以便在最后阶段产生更高效的目标代码
第五阶段:目标代码产生
依赖于硬件系统和机器指令的含义把中间代码变换成特定机器上的目标代码,目标代码分为3类
汇编指令代码:需要汇编器将汇编代码(MOVE,ADD等语言)翻译成机器指令(01字符串)才能执行
绝对指令代码:是机器语言程序,可以直接执行,指令的地址是绝对地址
可重定位指令代码:地址是相对地址,能从内存的任何位置进行装载。支持模块化的软件开发。需要通过链接程序进行装配,将相对地址替换成绝对地址,从而变成可执行文件才能执行
编译程序的结构
编译程序的结构与编译程序的5个过程相对应,
1.词法分析器
2.语法分析器
3.语义分析于中间代码生成器
4.优化段
5.目标代码生成器
6.符号表管理和出错处理,此结构与每个阶段都有联系
符号表管理:存放一些合法的符号及其相关信息
出错处理:即使用的编译器能够发现源程序中的错误,将其发送给程序员,包括两类错误,语法错误和语义错误:
1.语法错误:源程序中不符合语法(或词法)规则的错误,如非法字符,括号不匹配等
2.语义错误:源程序中不符合语义规则的错误,如变量声明错误,作用域错误,类型不一致等
其结构图如下:

编译过程的分解
由于词法分析,语法分析与中间代码产生与目标机器无关,因此可以以中间代码为例,将编译过程分解为编译前端和编译后端(能够使程序更加清晰,优化更加充分,提高程序的可移植性):
编译前端的工作是源程序通过词法编译器、语法编译器、中间代码产生以及与机器无关优化的处理,实现从源语言到中间语言的转换
编译后端则是与机器有关的优化以及目标代码的产生,实现中间语言到目标代码的转换
编译器的自举和移植
编译过程可用表示T-Diagram图表示,通过I代码将S语言转换成能够在T机器上运行的文件:

编译程序的生成
方式一:通过已有的高级语言去编写新的高级语言的程序
在A机器上有一个能够将L语言翻译成A机器的机器代码的P1代码,那么可以用L语言去编写一个程序PA(该程序的目的是实现P语言到A机器的编译),从而使得高级语言P可以在A机器上执行。
编译示意图过程如下:

用H编译器实现I语言到K语言的转换,在此基础上,用I语言编写一个编译器I,实现从S语言到T语言的转换,借助H编译器,可以将I编译器先转换为基于K语言的编译器,实现S到T语言基于K编译器的转换,类似于CPython编译器的原理
方式二:通过自编译方式,通过不断的对编译器进行功能的增加,从而达到一个符合所有条件的最终编译器
编译程序的自举
自举就是用该机器A的低级语言去编写一个简单的微型编译器A1,然后在该微型编译器的基础上增加更多功能,形成具有更多功能的编译器A2,用A2去进行编译得到最终需要的编译器,这便是编译器的自举
还是需要用M语言写一个具有很小功能的S编译器,然后用其去编译加入了更多功能的编译器,然后用编译出来的更多功能的编译器去编译,这样就得到了最终需要的编译器,这便是自举。过程示意图如下:

编译程序的移植
编译程序的移植,其目的是解决高级语言的跨平台性,使同一种语言能够在不同的机器上运行:
移植的关键在于产生交叉编译器

已知有一个M编译器,可以在M机器上编译S语言,因此,可用S语言去编写一个编译器S,在K机器上能够对S语言进行编译,又因为S语言可用M语言编译,因此将S编译器用M编译器进行编译得到M程序,实现S语言在K机器上的编译过程,此时M便是交叉编译器,得到交叉编译器之后,便可以编译在K机器上的S编译器了,将编译器S编译成K语言的编译器K,便可以得到在K机器上运行的K编译器了,如图所示:


6345

被折叠的 条评论
为什么被折叠?



