我们在编译c程序的时候其过程一般点击一个图标,或者执行一个命令就完成了。但实际的过程可不是这么简单的。在使用gcc编译程序时,它就把这个过程分成了四布来完成。实际上gcc是一个编译环境包含这四步的工具,这四步分别是:
(1)预处理:(Pre-Processing)
(2)编译:(Compiling)
(3)汇编:(Assembling)
(4)链接:(Linking)
使用gcc,我们可以根据需要让程序的编译停在任何的阶段。以便检查或使用编译器在该阶段输出的信息,或者对最后生成的文件进行控制,以便通过加入不同数量或种类的调试代码为今后的调试做准备。
用一个最简单的程序编译程来观察编译器工作。下面是实验的源程序hello.c。
#include <stdio.h> int main() { printf("Hello,world!"); return 0; }
(1)在预处理阶段,预处理器(cpp)处理。输入的是C语言的源文件。这个阶段主要处理文件中的预处理语句,也就是通常由#开头的语句,如#include,#define,#ifdef等。这个过程会生成一个中间文件,但一般不会专门生成这种文件,所以在我们编译程序的时候不会看到类似的文件。如果必须要生成这样的文件,可以使用下面的Shell命令。
gcc -E hello.c -o hello.i
使用这个命令生成的是一个仍然可以用vim察看的文件,只不过由一个只有7行代码的程序变成了一个有800多行代码的程序,原因是应为在生成的hello.i文件中把include进的库的相关代码导入了。
(2)在编译阶段,编译器(ccl)处理。编译器将中间文件hello.i,编译后生成汇编语言文件*.s,使用的Shell命令是。
gcc -S hello.i -o hello.s
.file "hello.c" .section .rodata .LC0: .string "Hello,world!" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 andl $-16, %esp subl $16, %esp movl $.LC0, (%esp) call printf movl $0, %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Debian 4.7.2-5) 4.7.2" .section .note.GNU-stack,"",@progbits(3)在汇编阶段,汇编器(as)将输入的hello.s转换成二进制机器代码文件 *.o。这个阶段所使用的命令是。
gcc -c hello.s -o hello.o这个阶段会生成一个二进制的文件hello.o,现在已经不可以使用vim察看 了,但是还可以使用od来察看,可以看到文件内容是如下一些的数字。
0000000 042577 043114 000401 000001 000000 000000 000000 000000 0000020 000001 000003 000001 000000 000000 000000 000000 000000 0000040 000424 000000 000000 000000 000064 000000 000000 000050 0000060 000015 000012 104525 101745 170344 166203 143420 022004 0000100 000000 000000 176350 177777 134377 000000 000000 141711 0000120 062510 066154 026157 067567 066162 020544 000000 041507 0000140 035103 024040 062504 064542 067141 032040 033456 031056 0000160 032455 020051 027064 027067 000062 000000 000024 000000 0000200 000000 000000 075001 000122 076001 000410 006033 002004 0000220 000610 000000 000034 000000 000034 000000 000000 000000 0000240 000034 000000 040400 004016 001205 006502 054005 006305 0000260 002004 000000 027000 074563 072155 061141 027000 072163 0000300 072162 061141 027000 064163 072163 072162 061141 027000 0000320 062562 027154 062564 072170 027000 060544 060564 027000 0000340 071542 000163 071056 062157 072141 000141 061456 066557 0000360 062555 072156 027000 067556 062564 043456 052516 071455 0000400 060564 065543 027000 062562 027154 064145 063137 060562 0000420 062555 000000 000000 000000 000000 000000 000000 000000 0000440 000000 000000 000000 000000 000000 000000 000000 000000 0000460 000000 000000 000000 000000 000000 000000 000037 000000 0000500 000001 000000 000006 000000 000000 000000 000064 000000 0000520 000034 000000 000000 000000 000000 000000 000004 000000 0000540 000000 000000 000033 000000 000011 000000 000000 000000 0000560 000000 000000 001744 000000 000020 000000 000013 000000 0000600 000001 000000 000004 000000 000010 000000 000045 000000 0000620 000001 000000 000003 000000 000000 000000 000120 000000 0000640 000000 000000 000000 000000 000000 000000 000004 000000 0000660 000000 000000 000053 000000 000010 000000 000003 000000 0000700 000000 000000 000120 000000 000000 000000 000000 000000 0000720 000000 000000 000004 000000 000000 000000 000060 000000 0000740 000001 000000 000002 000000 000000 000000 000120 000000 0000760 000015 000000 000000 000000 000000 000000 000001 000000 0001000 000000 000000 000070 000000 000001 000000 000060 000000 0001020 000000 000000 000135 000000 000035 000000 000000 000000 0001040 000000 000000 000001 000000 000001 000000 000101 000000 0001060 000001 000000 000000 000000 000000 000000 000172 000000 0001100 000000 000000 000000 000000 000000 000000 000001 000000 0001120 000000 000000 000125 000000 000001 000000 000002 000000 0001140 000000 000000 000174 000000 000070 000000 000000 000000 0001160 000000 000000 000004 000000 000000 000000 000121 000000 0001200 000011 000000 000000 000000 000000 000000 001764 000000 0001220 000010 000000 000013 000000 000010 000000 000004 000000 0001240 000010 000000 000021 000000 000003 000000 000000 000000 0001260 000000 000000 000264 000000 000137 000000 000000 000000 0001300 000000 000000 000001 000000 000000 000000 000001 000000 0001320 000002 000000 000000 000000 000000 000000 001434 000000 0001340 000260 000000 000014 000000 000011 000000 000004 000000 0001360 000020 000000 000011 000000 000003 000000 000000 000000 0001400 000000 000000 001714 000000 000025 000000 000000 000000 0001420 000000 000000 000001 000000 000000 000000 000000 000000 0001440 000000 000000 000000 000000 000000 000000 000001 000000 0001460 000000 000000 000000 000000 000004 177761 000000 000000 0001500 000000 000000 000000 000000 000003 000001 000000 000000 0001520 000000 000000 000000 000000 000003 000003 000000 000000 0001540 000000 000000 000000 000000 000003 000004 000000 000000 0001560 000000 000000 000000 000000 000003 000005 000000 000000 0001600 000000 000000 000000 000000 000003 000007 000000 000000 0001620 000000 000000 000000 000000 000003 000010 000000 000000 0001640 000000 000000 000000 000000 000003 000006 000011 000000 0001660 000000 000000 000034 000000 000022 000001 000016 000000 0001700 000000 000000 000000 000000 000020 000000 064000 066145 0001720 067554 061456 066400 064541 000156 071160 067151 063164 0001740 000000 000000 000014 000000 002401 000000 000021 000000 0001760 005002 000000 000040 000000 001002 000000 0001774
gcc hello.o -o hello