计算机小白对C语言“hello world”程序的深入理解
这篇文章主要是自身对***hello world***程序在计算机系统中如何运行的理解和体会,希望阅读这篇文章对你有些许帮助,可能在我们的日常编码中,对于hello world程序很熟悉,输出hello world,感觉像1+1=2一样,理所当然,但是往往在编码中,我们不仅仅要知其然,还要知其所以然,废话我就不多说了,下面是我的自身体会。
下面展示一些 内联代码片
。
// A code block
// hello.c程序代码
#include <stdio.h>;
int main()
{
printf("hello world\n");
return 0;
}
代码很简单,首先理解我们需要从生命周期开始,它是从一个源文件开始的,源程序(或者说源文件)实际上就是一个由1和0组成的位(又称为比特)序列,每一个字节表示程序中的某些文本字符。如果说我们用ASCII码将其替换,就会变成文本文件,又称为二进制文件。
为了能在系统上运行hello.c程序,必须把每条C语句变成低级机器语言指令,然后把这些指令按照一种称为可执行目标程序的格式打包好,并且需要以二进制磁盘文件的形式存放起来,目标程序又称为可执行文件,如果说我们在Unix系统上运行,是从源程序到目标文件,由编译器驱动程序完成的。
下面展示一些 内联代码片
。
// A code block
// Unix系统运行
linux> gcc -o hello hello.c
在这里GCC编译器驱动程序读取源程序文件 hello.c ,并把翻译成一个可执行目标文件 hello。 但是我们需要了解翻译过程可被分成四个阶段完成,执行这四个阶段的程序(预处理器 ,编译器 ,汇编器, 和链接器)一起构成了编译系统。如图一
首先是预处理阶段,预处理器(cpp)根据以字符#开头的命令,修改原始的C程序,如代码中的下面展示一些 内联代码片
。
// A code block
// An highlighted block
#include <stdio.h>;
命令告诉预处理器读取系统头文件stdio.h的内容,把它直接插入程序文本中,会得到另一个C程序,通常是以.i作为文件扩张名。
编译阶段。编译器(ccl)将文本文件hello.i 翻译成文本文件 hello.s,在它之中有一个汇编语言程序,其中还包含了函数 main的定义下面展示一些 内联代码片
。
// A code block
// An highlighted block
1 main:
2 subq $8, %rsp
3 movl $.LCO, %edi
4 call puts
5 movl $0, %eax
6 addq $8, %rsp
7 ret
在定义中2~7行的每一条语句都以一种文本格式描述了一条低级机器语言指令。
汇编阶段,接下来,汇编器(as)将hello.s翻译成机器语言指令,并把这些指令打包成一种叫做可重定位目标程序的格式,且将结果保存在目标文件hello.o中。此时hello.o文件是一个二进制文件,在他中有17个字节是函数main的指令编码,但是此时我们在文件编辑器中打开hello.o文件时,看到是一堆乱码
最后则是链接阶段,但是我们会注意到,hello程序所调用printf函数,它是C编译器提供的标准库中的函数,所以printf函数会存在一个名为printf.o的单独的预编译好了的目标文件中,因为我们要输出hello world,那么这个文件,必须以某种方式合并到我们的hello.o程序中,而链接器(id)就负责处理这种合并,最后我们便得到一个hello文件,它是一个可执行目标文件,被加载到内存中,由系统执行。