十. 链接概述和目标文件格式
1. 可执行文件的生成过程
-
预处理:处理源文件中以 “#” 开头的预编译指令,包括:
gcc -E hello.c //生成预处理文件hello.i
-
删除 "#define" 并展开所定义的宏
-
处理所有条件预编译指令,如 "#ifdef","#if","#endif"等
-
插入头文件到"#include"处,可以递归进行处理
-
删除所有的注释 "//" 和 “/* */
-
添加行号和文件名标识,以便编译时编译器产生调试用的行号信息
-
保留所有#progma编译指令(编译器需要用 )
经过预处理后,得到的文件是预处理文件(如,hello.i),它还是一个可读的文本文件,但不包括任何宏定义
809 810 /*以下是hello.i文件中的内容一部分,预处理产生的结果很多,个人所写的代码在最后几行*/ 811 extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; 812 # 873 "/usr/include/stdio.h" 3 4 813 extern FILE *popen (const char *__command, const char *__modes) ; 814 815 816 817 818 819 extern int pclose (FILE *__stream); 820 821 822 823 824 825 extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__)); 826 # 913 "/usr/include/stdio.h" 3 4 827 extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); 828 829 830 831 extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; 832 833 834 extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); 835 # 943 "/usr/include/stdio.h" 3 4 836 837 # 2 "hello.c" 2 838 int main() 839 { 840 printf("hello,world\n"); 841 return 0; 842 }
-
-
编译:
-
编译过程就是将预处理得到的预处理文件(如,hello.i) 进行词法分析,语法分析,语义化分析并优化,生成汇编文件
-
用来进行编译处理的程序称为编译程序(编译器,Compiler)
-
经过编译后,得到的汇编代码文件(如 hello.s)还是可读的文本文件,CPU无法理解和执行它
-
编译命令
gcc -S hello.i
-
gcc命令实际上是具体程序(如ccp, cc1,as等)的包装命令,用户通过gcc命令来使用具体的预处理程序ccp,编译程序cc1和汇编程序as等
-
-
汇编:
-
汇编代码文件(由汇编指令构成)称为汇编语言源程序
-
汇编程序(汇编器)用来将汇编语言程序转换为机器指令序列(机器语言程序)
-
汇编指令和机器指令一一对应,前者是后者的符号表示,它们都属于机器级指令,所构成的程序称为机器级代码
-
汇编命令
gcc -c hello.s
-
汇编结果是一个可重定位目标文件(如,hello.o),其中包含的是不可读的二进制代码,必须用相应的工具软件来查看内容或者反汇编
-
-
链接:
-
预处理,编译和汇编三个阶段针对一个模块(一个*.c文件)进行处理,得到对应的一个可重定位目标文件(一个 *.o文件)
-
链接过程将多个可重定位目标文件合并以生成可执行目标文件
-
链接命令
gcc -static -o prog mian.o test.o 或者 ld -static -o prog main.o test.o -static表示静态链接,如果不指定-o选项,则可执行文件名字为"a.out"
-