-
Notifications
You must be signed in to change notification settings - Fork 1.3k
一个 Hello world 程序在计算机中是怎样运行的
cxuan edited this page Jul 10, 2020
·
2 revisions
C 语言程序成为高级语言的原因是它能够读取并理解人们的思想。然而,为了能够在系统中运行 hello.c
程序,则各个 C 语句必须由其他程序转换为一系列低级机器语言指令。这些指令被打包作为可执行对象程序
,存储在二进制磁盘文件中。目标程序也称为可执行目标文件。
在 UNIX 系统中,从源文件到对象文件的转换是由编译器
执行完成的。
gcc -o hello hello.c
gcc 编译器驱动从源文件读取 hello.c
,并把它翻译成一个可执行文件 hello
。这个翻译过程可用如下图来表示
这就是一个完整的 hello world 程序执行过程,会涉及几个核心组件:预处理器、编译器、汇编器、连接器,下面我们逐个击破。
-
预处理阶段(Preprocessing phase)
,预处理器会根据开始的#
字符,修改源 C 程序。#include <stdio.h> 命令就会告诉预处理器去读系统头文件stdio.h
中的内容,并把它插入到程序作为文本。然后就得到了另外一个 C 程序hello.i
,这个程序通常是以.i
为结尾。 - 然后是
编译阶段(Compilation phase)
,编译器会把文本文件hello.i
翻译成文本hello.s
,它包括一段汇编语言程序(assembly-language program)
。这个函数包含 main 函数的定义,如下
main:
subq $8, %rsp
movl $.LCO, %edi
call puts
movl &0, %eax
addq $8, %rsp
ret
上面定义中的 2 - 7 描述了一种低级语言指令。汇编语言是非常有用的,因为它能够针对不同高级语言来提供自己的一套标准输出语言。
- 编译完成之后是
汇编阶段(Assembly phase)
,这一步,汇编器 as
会把 hello.s 翻译成机器指令,把这些指令打包成可重定位的二进制程序(relocatable object program)
放在 hello.c 文件中。它包含的 17 个字节是函数 main 的指令编码,如果我们在文本编辑器中打开 hello.c 将会看到一堆乱码。 - 最后一个是
链接阶段(Linking phase)
,我们的 hello 程序会调用printf
函数,它是 C 编译器提供的 C 标准库中的一部分。printf 函数位于一个叫做printf.o
文件中,它是一个单独的预编译好的目标文件,而这个文件必须要和我们的 hello.o 进行链接,连接器(ld)
会处理这个合并操作。结果是,hello 文件,它是一个可执行的目标文件(或称为可执行文件),已准备好加载到内存中并由系统执行。