从字符串变为程序
复习
- 从源代码到可执行文件:编译、汇编、链接的完整流水线
- 字符串:字符的序列
- 数据结构与算法:树、图、哈希表等工具
TL;DR
- 编译器把源代码翻译成目标代码
- 它大致分为前端、中端、后端
- 前端理解源码结构,后端生成机器指令
- 源码一路上会经历好几种中间形态
正文
还记得讲程序与编程基础时,我们留下了一个黑箱吗?当时说:一段源代码经过“编译、汇编、链接”变成可执行文件,但内部具体怎么变的,暂时当作黑箱。
现在,我们终于有足够的工具(树、图、哈希表、递归、动态规划……)来打开它了。这就是编译原理要讲的事。
编译器是什么
编译器的职责,一句话就能说清:把一种语言写的程序(源代码),翻译成另一种语言写的程序(目标代码)。
它像一位翻译官:输入是一串字符,输出是能在机器上运行的指令。从“人写的字”,到“机器执行的命令”,中间要跨过巨大的鸿沟。
为什么不能一步到位
既然只是翻译,为什么不能直接“看一眼源码就吐出机器码”?
因为这两者之间的差距太大了。源代码有嵌套结构、有类型、有作用域、有复杂表达式;机器指令只认寄存器、内存地址和跳转。一步跨过去,几乎不可能写对。
于是,编译器把这件事拆成了一连串阶段,每一步只解决一小部分问题:
- 前端:读懂源码——词法分析、语法分析、语义分析
- 中端:翻译成与具体机器无关的中间表示,并做优化
- 后端:把中间表示落到具体机器的指令上
这又是我们熟悉的老办法:面对一个复杂问题,把它拆成一层层可以分别搞定的阶段。 每一层的输出,就是下一层的输入。
跟着一段源码走一遍
接下来的章节,我们会始终跟着一小段源代码,看它在编译器内部一路变成什么形态:先是字符,再是词,然后是语法树,接着是中间表示,最后是机器指令。
先从最底层的一步开始:怎样把一串字符,切成编译器认得的一个个“词”?
思考题 1
编译器为什么不能直接把源代码变成机器指令,而要分成多个阶段?
思考题 2
前端和后端,大致各负责什么?
小结
知识点
- 编译器把源代码翻译为目标代码
- 整体分为前端、中端、后端
- 分阶段是为了跨越源码与机器码之间的鸿沟
- 源码在编译过程中会经历多种中间形态
参考资料
- Wikipedia(zh):编译器:把源代码翻译为目标代码的程序
- Wikipedia(zh):编译原理:编译器构造的理论与阶段划分
思考题答案(仅供参考)
思考题 1
因为源码与机器指令之间差距太大:源码有嵌套结构、类型、作用域等,机器指令只认寄存器和地址。一步转换几乎无法写对,分阶段可以让每一步只解决一小部分问题,逐层推进。
思考题 2
前端负责“读懂”源码:词法分析、语法分析、语义分析,产出程序的结构表示;后端负责把中间的表示落到具体机器的指令上,包括指令选择、寄存器分配、生成汇编等。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪