这一章节主要是通过介绍HelloWorld程序的生命周期,对计算机系统的主要概念做了一个概述

The Lifetime of Hello Program(Hello程序的生命周期)

1654706859696.png

  1. #include<stdio.h>
  2. int main(){
  3. printf("Hello World\n");
  4. return 0;
  5. }

源代码编写完成之后,保存得到一个后缀名 .c 的文件 —— hello.c

The Compilation System(编译系统)

  1. linux> gcc -o hello hello.c

1654707645754.png

  • 第一阶段 —— 预处理阶段

预处理器会根据以#开头的代码,来修改原始程序
例如 hello 程序中引入了头文件 —— stdio.h
预处理器会读取该头文件中的内容,将其中的内容直接插入到源程序中,结果就得到了另外一个 C 程序,这个经过预处理器处理后得到的文件通常以 .i 结尾
说白了就是,hello.c 经过预处理器后得到 hello.i,这个hello.i 仍旧是一个文本文件

  • 第二阶段 —— 编译阶段

编译器将 hello.i 文件翻译成 hello.s 文件,这一过程我们称为编译,其中编译这一阶段包括词法分析、语法分析、语义分析,中间代码生成以及优化等等一系列的中间操作
(更进一步了解,可以阅读《编译原理》,也许几年内我会做编译原理的笔记)

  • 第三阶段 —— 汇编阶段

汇编 器根据 指令集 将汇编程序 hello.s 翻译成机器指令,并且把这一系列的机器指令按照固定的规则进行打包,得到可重定位目标文件——hello.o
此时 hello.o 虽然是一个二级制的文件,但是还是不能执行,还要经历最后一个阶段——链接

  • 第四阶段 —— 链接阶段

在hello这个程序中,我们调用了printf函数。这个函数是标准C库中的一个函数。每一个C语言的编译器都会提供。通俗的讲就是当你调用printf这个函数时,编译器就知道你要在屏幕上打印输出内容,它会将这行代码翻译成计算机可以理解的指令。这个printf函数在是在名为printf.o的文件中,这个文件是一个提前编译好的目标文件,连接器(ld)负责把hello.o 和 printf.o 进行合并,当然这个合并是要遵循一定规则的。正是因为链接器要对hello.o 和 printf.o 进行调整,所以 hello.o 才会被称之为可重定位目标文件,最终经过链接阶段可以得到可执行目标文件——hello
此时,得到的 hello 就可以被加载到内存中执行了

Why programmers need to understand how compilation system work?(为何程序员有必要理解编译系统是如何工作的?)

Reasons(原因):

  • Optimizing program performance(优化程序性能)
  • Understanding link-time errors(理解链接时出现的错误)
  • Avoiding security holes(避免安全漏洞)

待补充:
对汇编、指令集、链接的引用
对三个原因的举例