转载

你不知道的hello world后面的故事

最近打算巩固计算机基础知识,网上一本评价极高的教材—— 深入理解计算机系统 ,下面要将讲的内容来自第一章一个小例子,不过对我们了解C语言如何从源程序到最终的可执行程序很有帮助,下面让我们开始吧。

一步到位的hello world

首先一个简单的C语言版本的hello world例子,保存在文件 hello.c 中。

#include <stdio.h>  int main() {     printf("hello world/n"); }

一般而言,我们通常可以使用 gcc 命令将其转化为可执行程序

gcc -o hello hello.c

执行上面命令后,就会在当前目录生产一个 hello 的可执行文件。在 Centos 64位 机器上执行 file hello ,可以得到

hello: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), not stripped

直接执行 ./hello 即可在控制台输出 hello world

条分缕析的hello world

为了说明C语言源程序是如何转化为最终的可执行文件,首先看下面这个图

你不知道的hello world后面的故事

下面来分布讲解

预处理(Preprocessor)阶段

这个阶段处理 # 开头的指示语句, hello.c 中的 #include<stdio.h> 告知预处理器去加载 stdio.h 的内容,并把它插入到当前位置。

cpp hello.c > hello.i file hello.i # hello.i: ASCII C program text

编译(Compiler)阶段

这个阶段把C语言源程序编译为汇编程序,不同高级语言经由其编译器处理后,得到的同样的汇编语言。

cc -S hello.i   #会生成 hello.s 文件 file hello.s # hello.s: ASCII assembler program text

组装(Assembly)阶段

这一阶段把汇编语言翻译为机器码,结果保存在称为 relocatable object program/file 的文件中,一般以 .o 结尾。

as -o hello.o hello.s file hello.o # hello.o: ELF 64-bit LSB relocatable, AMD x86-64, version 1 (SYSV), not stripped

链接(Linking)阶段

注意到我们的 hello.c 程序使用了 printf 函数,它是由C语言的标准库函数,由C语言编译器提供, printf 函数应该会存在于一个 printf.o 的文件中,我们需要某种手段把它合并到我们的 hello.o 中,链接器就是做这件事的。最终生成的为一个称为 executable object file 的文件,它可以被装载进内存并且执行。

正文到此结束
Loading...