Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

从字符串变为程序

复习

  • 从源代码到可执行文件:编译、汇编、链接的完整流水线
  • 字符串:字符的序列
  • 数据结构与算法:树、图、哈希表等工具

TL;DR

  • 编译器把源代码翻译成目标代码
  • 它大致分为前端、中端、后端
  • 前端理解源码结构,后端生成机器指令
  • 源码一路上会经历好几种中间形态

正文

  还记得讲程序与编程基础时,我们留下了一个黑箱吗?当时说:一段源代码经过“编译、汇编、链接”变成可执行文件,但内部具体怎么变的,暂时当作黑箱

  现在,我们终于有足够的工具(树、图、哈希表、递归、动态规划……)来打开它了。这就是编译原理要讲的事。

编译器是什么

  编译器的职责,一句话就能说清:把一种语言写的程序(源代码),翻译成另一种语言写的程序(目标代码)。

  它像一位翻译官:输入是一串字符,输出是能在机器上运行的指令。从“人写的字”,到“机器执行的命令”,中间要跨过巨大的鸿沟。

为什么不能一步到位

  既然只是翻译,为什么不能直接“看一眼源码就吐出机器码”?

  因为这两者之间的差距太大了。源代码有嵌套结构、有类型、有作用域、有复杂表达式;机器指令只认寄存器、内存地址和跳转。一步跨过去,几乎不可能写对。

  于是,编译器把这件事拆成了一连串阶段,每一步只解决一小部分问题:

  • 前端:读懂源码——词法分析、语法分析、语义分析
  • 中端:翻译成与具体机器无关的中间表示,并做优化
  • 后端:把中间表示落到具体机器的指令上

  这又是我们熟悉的老办法:面对一个复杂问题,把它拆成一层层可以分别搞定的阶段。 每一层的输出,就是下一层的输入。

跟着一段源码走一遍

  接下来的章节,我们会始终跟着一小段源代码,看它在编译器内部一路变成什么形态:先是字符,再是词,然后是语法树,接着是中间表示,最后是机器指令。

  先从最底层的一步开始:怎样把一串字符,切成编译器认得的一个个“词”?

思考题 1

  编译器为什么不能直接把源代码变成机器指令,而要分成多个阶段?

思考题 2

  前端和后端,大致各负责什么?

小结

知识点

  • 编译器把源代码翻译为目标代码
  • 整体分为前端、中端、后端
  • 分阶段是为了跨越源码与机器码之间的鸿沟
  • 源码在编译过程中会经历多种中间形态

参考资料

  1. Wikipedia(zh):编译器:把源代码翻译为目标代码的程序
  2. Wikipedia(zh):编译原理:编译器构造的理论与阶段划分

思考题答案(仅供参考)

思考题 1

  因为源码与机器指令之间差距太大:源码有嵌套结构、类型、作用域等,机器指令只认寄存器和地址。一步转换几乎无法写对,分阶段可以让每一步只解决一小部分问题,逐层推进。

思考题 2

  前端负责“读懂”源码:词法分析、语法分析、语义分析,产出程序的结构表示;后端负责把中间的表示落到具体机器的指令上,包括指令选择、寄存器分配、生成汇编等。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪