gcc编译与程序的4个执行阶段解读
在使用GCC编译程序时,其编译过程可以分为4个阶段:预处理(Pre-Processing) -> 编译(Compling) -> 汇编(Assembling) -> 连接(Linking) .
程序员完全可以根据自己的需要让gcc在编译的任何一个阶段结束,检查活使用编译起在该阶段输出的信息,或者对其生成的二进制文件进行控制。
我想通过一个Hello World程序对GCC的编译过程有进一步的认识。
- [Xredman@localhost demo]$ cat test.c
- #include <stdio.h>
- int main(void)
- {
- printf("Hello World\n");
- return 0;
- }
首先来个一步到位编译成可执行文件
- [Xredman@localhost demo]$ gcc -Wall test.c -o test.o
- [Xredman@localhost demo]$ ./test.o
- Hello World
OK,这是我日常生活中所用的,以下将分步骤演示
A.预处理(Pr-Processing)
- gcc -E test.c -o test.i
打开test.i文件,吓我嘛,编译器原来为我们做了这么多事,辛苦了。这里主要负责展开在源文件中定义的宏,并向其中插入#include语句所包含的内容
- # 1 "test.c"
- # 1 "<built-in>"
- # 1 "<command line>"
- # 1 "test.c"
- # 1 "/usr/include/stdio.h" 1 3 4
- # 28 "/usr/include/stdio.h" 3 4
- # 1 "/usr/include/features.h" 1 3 4
- # 329 "/usr/include/features.h" 3 4
- # 1 "/usr/include/sys/cdefs.h" 1 3 4
- # 313 "/usr/include/sys/cdefs.h" 3 4
- # 1 "/usr/include/bits/wordsize.h" 1 3 4
- # 314 "/usr/include/sys/cdefs.h" 2 3 4
- # 330 "/usr/include/features.h" 2 3 4
- # 352 "/usr/include/features.h" 3 4
- # 1 "/usr/include/gnu/stubs.h" 1 3 4
- # 1 "/usr/include/bits/wordsize.h" 1 3 4
- # 5 "/usr/include/gnu/stubs.h" 2 3 4
- # 1 "/usr/include/gnu/stubs-32.h" 1 3 4
- ....
B.编译(Compiling)
- [Xredman@localhost demo]$ gcc -S test.i -o test.s
编译之后应该就是汇编程序了吧,查看内容如下
- [Xredman@localhost demo]$ cat test.s
- .file "test.c"
- .section .rodata
- .LC0:
- .string "Hello World"
- .text
- .globl main
- .type main, @function
- main:
- leal 4(%esp), %ecx
- andl $-16, %esp
- pushl -4(%ecx)
- pushl %ebp
- movl %esp, %ebp
- pushl %ecx
- subl $4, %esp
- movl $.LC0, (%esp)
- call puts
- movl $0, %eax
- addl $4, %esp
- popl %ecx
- popl %ebp
- leal -4(%ecx), %esp
- ret
- .size main, .-main
- .ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-48)"
- .section .note.GNU-stack,"",@progbits
C.汇编(Assembling)
汇编这一步是将汇编程序翻译成机器码,这也就决定了生成的程序能运行在哪种平台下,传说中GCC将调用gas汇编器
- [Xredman@localhost demo]$ gcc -c test.s -o test.o
D.连接(Linking)
这是最后一步,将生成的目标文件和其所依赖的库文件进行连接,生成一个可执行文件。
- [Xredman@localhost demo]$ gcc test.o -o test
- [Xredman@localhost demo]$ ./test
- Hello World
OK,练习完毕,我已经知道GCC的基本工作过程了。