C++脚本的执行过程, since 2020-11-08
(2020.11.08 Sun)
基本执行过程:源码编辑、预处理、编译、优化、汇编、链接、加载
源代码编辑
略
预处理preprocessing
读源程序,处理其中的伪指令(用#加载的)和特殊符号。
伪指令的四个方面:
- 宏定义,如#define xxx,#undef
- 条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等,prep将那些不必要的代码过滤掉
- 头文件的包含指令,#include,prep将把头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对其进行处理,用<>包含的文件是系统提供的,一般被放在/usr/include目录下,用双引号""包含的文件是开发人眼自己定义的头文件,这些文件一般与源程序放在同一目录下
- 特殊符号,prep程序可以识别一些特殊符号,比如源程序中出现的LINE标识被解释为当前行号,以十进制,FILE被解释为当前被编译的源程序的名称。prep程序对于在源程序中出现的这些串将用合适的值进行替换。
可用下面指令做预处理
$gcc -E file.c -o file.i # -E代表只进行预处理
$cpp file.c > file.i #另一种预处理指令,cat file.i即可查看处理后的代码
预处理完成的是替换工作,生成一个没有宏定义、条件编译指令、特殊符号的输出文件。文件含义相同,但是内容不同。
编译compilation
编译器compiler对程序进行编译,检察错误,生成目标文件,该目标文件中含有汇编代码。编译过程是把预处理完成的文件进行一些列的词法分析,语法分析,语义分析和优化,并生成汇编代码。
$gcc -S file.i -o file.s
$/usr/lib/gcc/i486-linux-gnu/4.4/cc1 file.c #另一种编译方法
编译过程是以c/c++文件为单位进行的,没有该文件就没法编译。预编译得到的输出文件中,有常量的定义,和编程语言的关键字。编译程序通过语法分析和词法Fenix,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
优化
优化的一部分是对中间代码的优化,不依赖于具体的计算机。主要工作是删除公共表达式、循环油画、复写传播,以及无用赋值的删除等。
另一部分针对目标代码的生成而进行,与电脑的硬件结构密切相关,主要关注如何充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次数。此外还会关注如何根据电脑硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码更短,执行效率更高。
汇编assembly
汇编过程是指把汇编语言代码翻译成目标机器指令的过程。对于C源程序,都要经过这个步骤得到相应的目标文件,目标文件存放的就是与源程序等效的目标的机器语言代码
$gcc -c file.c -o file.o
$as file.s -o file.co #另一种
通常一个目标文件至少有两个段,代码段和数据段。代码段中包含的主要是程序的指令,一般是可读和可执行的,但一般不可写。数据段主要存放程序中要用到的各种全局变量或静态数据,一般都是可读,可写,可执行。
链接linking
在这一步链接器linker将超过1个的目标文件或库文件连接并生成可执行文件。
$ld -static xxx.o xxx. -start- group xxx xxx xxx #待查
主要工作是将目标文件彼此相连接,并将一个文件中引用的符号同该符号在另一个文件中的定义连接起来,使得所有目标文件成为一个能够被操作系统装入执行的统一整体。
链接处理分为两种
- 静态链接,函数的代码将从器所在的静态链接库中被拷贝到最终的可执行程序中。该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有苦衷的一个或一组相关函数的代码。
- 动态链接,函数的代码被放倒称作是动态链接库或共享对象的某个目标文件中。链接阶段只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中。此时所做的是在最终的可执行程序中记录下共享对象的名字和其他少量的登记信息。在可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚拟地址空间。动态链接程序根据可执行程序中记录的信息找到相应的函数代码。
加载loader
将可执行文件加载到内存中并运行。默认可执行文件的名字a.out。
脚本执行过程中的文件名
C源代码的文件名为xx.c,预处理器读xx.c并生成xx.i或xx.ii(C++),该文件中包含预处理代码。编译器读xx.i将其转化为汇编代码并生成xx.s,最终生成目标文件xx.o。链接器读xx.o文件,并连接其他的目标文件和库文件生成可执行文件xx.out/xx.exe。将可执行加载到内存中即可运行。
另外,一个叫做xx.bak的文件如果被生成,则它是程序文件的backup备份文件。