代码编译过程
来源:互联网 发布:渠道店面管理专员知乎 编辑:程序博客网 时间:2024/06/04 17:45
在编译代码时我们通常使用 gcc hello.c -o hello 即将hello.c文件编译成hello可执行文件。那么这其中编译器做了哪些工作?
从最简单的例子入手hello.c:
#include <stdio.h>int main(){ printf("hello\n"); return 0;}
《深入理解计算机系统》一书中给出编译器详细的工作流程图:
预处理
gcc -E hello.c -o hello.i
-E参数是告知编译器只执行预处理工作,不执行后续编译工作。
-E Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output.
预处理主要处理“#”开头的语句,具体包括如下过程:
- 将#define删除并展开所有宏定义。
- 处理所有条件预编译命令,例如“#if、#ifdef、#endif、#else、#elif”
- 处理#include命令,将被包含文件插入到命令处,这是一递归的过程,
- 保留所有#pragma编译器命令。
//短短的一个hello经过预处理后达到了800多行845 extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __lea f__)) ;846847848 extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __lea f__));849 # 943 "/usr/include/stdio.h" 3 4850851 # 8 "hello.c" 2852853 int main()854 {855 printf("hello\n");856 return 0;857 }
编译
gcc -s hello.i -o hello.s (或 /usr/lib/gcc/i686-linux-gnu/4.9/cc1 hello.c)
编译过程是把预处理完的文件进行词法、语法、语义分析及优化后产生汇编代码文件
(ccl所在路径和版本与具体系统有关)
//编译后产生的汇编代码文件 1 .file "hello.c" 2 .section .rodata 3 .LC0: 4 .string "hello" 5 .text 6 .globl main 7 .type main, @function 8 main: 9 .LFB0: 10 .cfi_startproc 11 leal 4(%esp), %ecx 12 .cfi_def_cfa 1, 0 13 andl $-16, %esp 14 pushl -4(%ecx) 15 pushl %ebp 16 .cfi_escape 0x10,0x5,0x2,0x75,0 17 movl %esp, %ebp 18 pushl %ecx 19 .cfi_escape 0xf,0x3,0x75,0x7c,0x6 20 subl $4, %esp 21 subl $12, %esp 22 pushl $.LC0 23 call puts
汇编
gcc -c hello.s -o hello.o(或 as hello.s –o hello.co )
该阶段汇编器(as)将 hello.s 翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序(relocatable object program)的格式,并将结果保存在目标文件 hello.o 中。hello.o 文件是一个二进制文件(前面预处理和编译产生的都是可识别的文本文件),它的字节编码是机器语言指令而不是字符。
如果用vim打开,会发现全是看不懂的乱码,原因就在一此。
链接
ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了文件的路径名)此处涉及到很多东西,暂时没弄懂
hello程序调用了 printf 函数,printf 函数存在于一个名为 printf.o 的单独的预编译好了的目标文件中,而这个文件必须以某种方式合并到我们的 hello.o 程序中。链接器(ld)就负责处理这种合并。结果就得到 hello 文件,它是一个可执行目标文件。
#have a good day
- C#代码编译过程
- c代码编译过程
- c++代码编译过程
- c#代码编译过程
- 代码编译过程
- 代码编译过程
- 代码编译过程
- C#代码的编译过程
- C代码编译过程分析
- Java代码编译过程简述
- java代码编译、执行过程
- C语言代码的整个编译过程
- u-boot 代码下载编译过程
- 模板的代码组织和编译过程
- webrtc android代码编译过程小结
- 代码的编译连接与执行过程
- java代码的编译和执行过程
- 编译 unity3d 的示例代码过程
- Linux下安装Tomcat
- Oracle redo log
- hadoop-1.2.1伪分布式安装
- sql语句放到外部xml文件里,读取操作
- 网络相关系列之三:通过GET和POST方法发送数据
- 代码编译过程
- 一张图看懂JavaScript中数组的迭代方法:forEach、map、filter、reduce、every、some
- 如何解决return没有输出的问题
- 关于sizeof(struct student)的问题
- 父div随着子div的高度改变而改变
- iphone
- HadoopJob监控
- centos6.5 nginx+tomcat部署
- linux的权限和用户管理