第二章:编译和链接_2

第二章:编译和链接_2

编译器做了什么

从直观来说,编译器就是将高级语言翻译成机器语言的一个工具。编译器的存在可以让程序员更加关注程序本身的逻辑,而尽量少考虑计算机本身的限制,如字长,内存大小,通信方式,存储方式。

编译过程一般可以分为6步, 扫描,语法分析,语义分析,源代码优化,代码生成和目标代码优化

2.2.1 词法分析

首先源代码被输入到 扫描器,扫描器的任务很简单,它只是简单地进行词法分析,运用一种类似于 有限状态机的算法可以很轻松地将源代码的字符序列分割成一系列的 记号(token)

词法分析产生的记号一般可以分为以下几类: 关键字,标识符,字面量(包含数字,字符串)和特殊符号(如加号,等号)。

在识别记号的同时,扫描器也完成了其他的工作。比如将标识符放到符号表,将数字,字符串常量存放到文字表中,以备后面的步骤使用。

有一个叫 lex的程序可以实现词法扫描。

2.2.2 语法分析

接下来 语法分析器将对由扫描器产生的记号进行语法分析,从而产生 语法树。整个过程采用了 上下文无关语法的分析手段,语法分析器产生的语法树就是以表达式为结点的树。

正如前面的词法分析有lex一样,语法分析有一个现成的工具叫做 yacc。它也像lex一样,可以根据用户给定的语法规则对输入的记号序列解析。

2.2.3 语义分析

语义分分析器来完成语义分析,语法分析仅仅是完成了对表达式的语法层面的分析,但是它并不了解这个语句是否真的有意义。编译器所能分析的语义是 静态语义,所谓静态语义是指在编译期可以确定的语义,与之对应的 动态语义就是只有在运行期间才能确定的语义。

静态语义通常包括声明和类型的匹配,类型的转换。

2.2.4 中间语言生成

现代的编译器有着很多层次的优化,往往在源代码级别有一个优化过程。我们这里所描述的源码级优化器在不同编译器中可能会有不同的定义或有一些其他差异。

源代码优化器往往将整个语法树转换成 中间代码,它是语法树的顺序表示,其实他已经是非常接近目标代码了。但是它一般跟目标机器和运行时环境是无关的,比如它不包含数据的尺寸,变量地址和寄存器的名字等。中间代码有很多种类型,在不同的编译器中有着不同的形式,比较常见的有 三地址码和P-代码

中间代码使得编译器可以被分为前端和后端。编译器前端负责生产机器无关的中间代码,编译器后端负责将中间代码转换成目标机器代码。

2.2.5 目标代码生成与优化

源代码级优化器产生中间代码标志着下面的过程都属于编译器后端,编译器后端主要包括 代码生成器目标代码优化器。代码生成器将中间代码转换成目标机器代码。目标代码优化器将上述的目标代码进行优化,比如选择合适的寻址方式,使用唯一来代替乘法运算,删除多余的指令等。

现代编译器有着异常复杂的结构,这是因为现代高级编程语言本身就非常的复杂。另外现代的计算机CPU也相当复杂,CPU本身采用诸如流水线,多发射,超标量等诸多复杂的特性。

经过这些扫描,语法分析,语义分析,源代码优化,代码生成和目标代码优化,编译器经过这么多步骤后,源代码终于被编译成了目标代码。但是这个目标代码中有一个问题 数组的地址和函数的地址还没有确定。如果我们要把目标代码使用汇编器编译成真正能够在机器上执行的指令,那么数组和函数的地址应该在哪得到呢?

这些问题就涉及到了链接:目标代码中有变量定义在其他的模块,该怎么办?事实上,定义其他模块的全局变量和函数在最终运行时的绝对地址都要在最终链接的时候才能确定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值