来Offer习题讲解专题 | 程序的编译、链接和执行

来Offer(LaiOffer)
4 min readJul 19, 2019

--

汤老师介绍:

来Offer(www.laioffer.com)金牌算法讲师。清华大学计算机系信息学竞赛保送生,美国哥伦比亚大学计算机系软件系统实验室博士生,曾在 OSDI、CACM 等操作系统领域最顶级学术会议和期刊上发表多篇论文。曾参与 Chrome 和 Google Cloud Platform 的研发工作。

同学们总是抱怨每次见到一道面试题都很难把它转化为程序源代码。然而不幸的是,即使是程序源代码对于计算机来说也还是太高级了。要想让计算机执行一段程序,我们必须把它翻译成最底层的机器指令才行。这其中要经历很多步骤。幸运的是有很多现成的工具可以帮助我们完成这个过程。今天我们就以 C 语言为例给大家做个简单介绍。(Java 还要更复杂一些,涉及到字节码和虚拟机,今天就不讲了。)

预处理(Preprocessing)

翻译一段 C 语言程序的第一步是预处理。这一步主要处理所有以“#”号开头的行。比如当我们遇到 `#include “header.h”` 的时候,就直接把 `header.h` 文件里的所有内容插入到这儿。由此可见,一段 C 语言程序经过预处理之后还是一段 C 语言程序。

编译(Compilation)

第二步是编译,也就是将一段 C 语言程序翻译为一段汇编语言程序。汇编语言比 C 语言要底层多了,基本上就是机器指令的文字版,每一行汇编语言对应着一条机器指令。往往 C 语言程序里的一行要被翻译成好几行汇编语言程序才行。不同的高级语言(如 C、Fortran、Pascal 等等)有不同的预处理器和编译器,但它们在经过编译之后都变成了同一种汇编语言,于是后面的步骤和工具大家都是通用的了。

汇编(Assembly)

第三步是汇编,即把文字版的汇编语言程序真正翻译成由 0 和 1 组成的机器指令,并把它们打包输出成一个 relocatable object program (下文简称目标文件)。如果说汇编语言程序人类还勉强能看懂,经过这一步之后得到的目标文件就真的是一堆二进制乱码了。

链接(Linking)

第四步是链接,用来把多个目标文件合并成一个可执行文件。比如说我们写了一个 hello world 程序,其中调用了 C 语言标准库里的 printf 函数来打印。我们的 hello world 的主函数和 printf 函数存放在两个不同的目标文件里,经过这一步之后它们就被合并到一起了。(这里讲的是静态链接。如果是动态链接的话,printf 在这一步暂时不合并进来,而是在下一步程序运行的时候才被加载。)

加载(Loading)

上一步所生成的可执行文件终于可以被操作系统加载运行了。操作系统会将这个可执行文件中的代码和数据从磁盘复制到内存中,并跳转到该程序的第一条指令处(也叫做入口点,entry point)开始执行。

最后用一张图给大家总结一下全过程:

(本文在写作过程中参考了 Randal E. Bryant 和 David R. O’Hallaron 所著的 Computer Systems: A Programmer’s Perspective 第三版。)

E/N/D

关于来Offer:

来Offer是硅谷最具实力的高科技在线教育和职业培训机构,通过提供高水平的IT培训课程和就业指导,帮助学员进军硅谷一二线科技公司。自2013年以来,来Offer已将3000+名中国工程师送入Facebook, Google等硅谷一线公司。

点此了解来Offer课程详情:

来Offer软件工程师旗舰核心课程

来Offer全栈开发项目实践课程

来Offer人工智能与数据科学强化课程

来Offer无人车系统课

--

--

来Offer(LaiOffer)
来Offer(LaiOffer)

Written by 来Offer(LaiOffer)

Develop technical knowledge. Improve programming skills. Build your career in software engineering.

No responses yet