0%

hello程序的一生

hello程序是我们梦开始的地方,尽管它非常简单,但是为了让它实现运行,系统的每个主要组成部分都需要协调工作,我们将通过跟踪hello程序的生命周期开始对系统的学习。

源程序

hello程序的生命周期是从一个源程序开始的,即程序员通过编辑器创建并保存的文本文件,由ASCII字符组成,其它的所有文件统称为二进制文件。

在终端中打开nano编辑器,写入hello.c文件内容:

1
2
3
4
5
6
#include <stdio.h>
int main(void)
{
printf("hello,world\n");
return 0;
}

保存后退出编辑器。

预处理、编译、汇编、链接

  • 预处理:在终端中输入命令:gcc -E hello.c -o hello.i 生成hello.i文件
  • 编译:在终端中输入命令:gcc -S hello.i -o hello.s 生成hello.s文件
  • 汇编:在终端中输入命令:gcc -c hello.s -o hello.o 生成hello.o文件
  • 链接:在终端中输入命令:gcc hello.o -o hello生成可执行文件hello

预处理

预处理程序对源程序中以字符#开头的命令进行处理,将include后面的.h头文件嵌入到源程序文件中,预处理程序的输出结果还是一个源程序文件(相当于将多个源程序文件拼接在一起),以i为扩展名。

编译

编译程序对预处理后的源程序进行编译,生成一个汇编语言源程序文件,以s为扩展名。

在本例中我们在终端输入命令查看hello.s文件:cat hello.s

汇编

汇编程序(as)对汇编语言源程序进行汇编,生成一个可重定位目标文件,以o为扩展名。这个文件中的数据和其他信息是以二进制表示的,所以终端中打开是乱码。

链接

链接程序(ld)将多个可重定位目标文件和标准库函数合并成一个可执行目标文件,简称可执行文件。在本例中,链接器将hello.o文件和标准库函数printf所在的可重定位目标模块printf.o进行合并,生成可执行文件hello。

执行

在此刻,hello源程序已没有了当初的模样,而是以二进制形式的可执行文件存储在磁盘上,在终端输入./hello命令,即可执行hello程序,输出“hello,world\n”。在此过程中,可执行文件被加载到内存中,由系统执行操作。

反汇编

反汇编即是指将可执行文件反汇编还原成汇编语言或其他语言。但通常反编译出来的程序与原程序会存在些许不同,虽然执行效果相同,但程序代码会发生很大的变化,就操作而言,反汇编是汇编的逆过程。

在终端输入命令:objdump -d hello.o得到反汇编代码

以上内容是由hello.o机器码反汇编而来,其和编译而来的hello.s格式存在着不同,hello.s在格式上来讲更加易读,更接近源代码的格式。而反汇编得来的代码中含有机器码和相应的操作符。此外,反汇编得来的代码显得更加精简,系统对此做了优化,去除了一部分无用而冗余的代码。