GCC之旅(1)--- GCC的编译流程

 

参考华清远见《嵌入式 linux 应用程序开发详解》第三章

后缀名的说明:

.i  已经过预处理的C原始程序

.ii  已经过预处理的C++原始程序

.s/.S  汇编语言原始程序

.h  预处理文件(头文件)

.o  目标文件

.a/.so  编译后的库文件

 

GCC编译流程分为4个步骤

1.       预处理(Preprocessing)

2.       编译(Compiling)

3.       汇编(Assembling)

4.       链接(Linking)

 

test.c

  1 #include <stdio.h>

  2 int main(void)

  3 {

  4         printf("Hello World!/n");

  5         return 0;

  6 } 

 

 

1.       预处理(Preprocessing):在这个阶段GCC将头文件包含进test.c文件,并生成文件test.i

 

执行下面命令生成test.i

[root@localhost gccinfo]# gcc -E test.c -o test.i

 

test.i的文件内容:

  1 # 1 "test.c"

  2 # 1 "<built-in>"

  3 # 1 "<command-line>"

  4 # 1 "test.c"

  5 # 1 "/usr/include/stdio.h" 1 3 4

  6 # 28 "/usr/include/stdio.h" 3 4

  7 # 1 "/usr/include/features.h" 1 3 4

  8 # 335 "/usr/include/features.h" 3 4

  9 # 1 "/usr/include/sys/cdefs.h" 1 3 4

 10 # 360 "/usr/include/sys/cdefs.h" 3 4

 ………….

750 # 2 "test.c" 2

751 int main(void)

752 {

753  printf("Hello World!/n");

754  return 0;

755 }

 

2.       编译(Compiling):在这个阶段GCC检查test.i代码的规范性,确定有没有语法错误。确认无误后,则把test.i转化为汇编代码文件test.s

执行下面命令生成test.s

[root@localhost gccinfo]# gcc -S test.i -o test.s

test.s的文件内容:

  1         .file   "test.c"

  2         .section        .rodata

  3 .LC0:

  4         .string "Hello World!"

  5         .text

  6 .globl main

  7         .type   main, @function

  8 main:

  9         leal    4(%esp), %ecx

 10         andl    $-16, %esp

 11         pushl   -4(%ecx)

 12         pushl   %ebp

 13         movl    %esp, %ebp

 14         pushl   %ecx

 15         subl    $4, %esp

 16         movl    $.LC0, (%esp)

 17         call    puts

 18         movl    $0, %eax

 19         addl    $4, %esp

 20         popl    %ecx

 21         popl    %ebp

 22         leal    -4(%ecx), %esp

 23         ret

 24         .size   main, .-main

 25         .ident  "GCC: (GNU) 4.3.0 20080428 (Red Hat 4.3.0-8)"

 26         .section        .note.GNU-stack,"",@progbits

 

3.       汇编阶段(Assembling):在这个阶段GCCtest.s文件中的汇编代码转化为目标机器的机器代码文件test.o,为二进制文件。

 

执行下面命令生成test.o

[root@localhost gccinfo]# gcc -c test.s -o test.o

 

执行以下命令产看test.o

[root@localhost gccinfo]# od -t c test.o

 

test.o文件内容:

0000000 177   E   L   F 001 001 001  /0  /0  /0  /0  /0  /0  /0  /0  /0

0000020 001  /0 003  /0 001  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0000040 354  /0  /0  /0  /0  /0  /0  /0   4  /0  /0  /0  /0  /0   (  /0

0000060  /v  /0  /b  /0 215   L   $ 004 203 344 360 377   q 374   U 211

0000100 345   Q 203 354 004 307 004   $  /0  /0  /0  /0 350 374 377 377

0000120 377 270  /0  /0  /0  /0 203 304 004   Y   ] 215   a 374 303  /0

0000140   H   e   l   l   o       W   o   r   l   d   !  /0  /0   G   C

0000160   C   :       (   G   N   U   )       4   .   3   .   0       2

0000200   0   0   8   0   4   2   8       (   R   e   d       H   a   t

0000220       4   .   3   .   0   -   8   )  /0  /0   .   s   y   m   t

0000240   a   b  /0   .   s   t   r   t   a   b  /0   .   s   h   s   t

0000260   r   t   a   b  /0   .   r   e   l   .   t   e   x   t  /0   .

0000300   d   a   t   a  /0   .   b   s   s  /0   .   r   o   d   a   t

0000320   a  /0   .   c   o   m   m   e   n   t  /0   .   n   o   t   e

0000340   .   G   N   U   -   s   t   a   c   k  /0  /0  /0  /0  /0  /0

0000360  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

*

0000420  /0  /0  /0  /0 037  /0  /0  /0 001  /0  /0  /0 006  /0  /0  /0

0000440  /0  /0  /0  /0   4  /0  /0  /0   +  /0  /0  /0  /0  /0  /0  /0

0000460  /0  /0  /0  /0 004  /0  /0  /0  /0  /0  /0  /0 033  /0  /0  /0

0000500  /t  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0   X 003  /0  /0

0000520 020  /0  /0  /0  /t  /0  /0  /0 001  /0  /0  /0 004  /0  /0  /0

0000540  /b  /0  /0  /0   %  /0  /0  /0 001  /0  /0  /0 003  /0  /0  /0

0000560  /0  /0  /0  /0   `  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0000600  /0  /0  /0  /0 004  /0  /0  /0  /0  /0  /0  /0   +  /0  /0  /0

0000620  /b  /0  /0  /0 003  /0  /0  /0  /0  /0  /0  /0   `  /0  /0  /0

0000640  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0 004  /0  /0  /0

0000660  /0  /0  /0  /0   0  /0  /0  /0 001  /0  /0  /0 002  /0  /0  /0

0000700  /0  /0  /0  /0   `  /0  /0  /0  /r  /0  /0  /0  /0  /0  /0  /0

0000720  /0  /0  /0  /0 001  /0  /0  /0  /0  /0  /0  /0   8  /0  /0  /0

0000740 001  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0   m  /0  /0  /0

0000760   -  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0 001  /0  /0  /0

0001000  /0  /0  /0  /0   A  /0  /0  /0 001  /0  /0  /0  /0  /0  /0  /0

0001020  /0  /0  /0  /0 232  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001040  /0  /0  /0  /0 001  /0  /0  /0  /0  /0  /0  /0 021  /0  /0  /0

0001060 003  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0 232  /0  /0  /0

0001100   Q  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0 001  /0  /0  /0

0001120  /0  /0  /0  /0 001  /0  /0  /0 002  /0  /0  /0  /0  /0  /0  /0

0001140  /0  /0  /0  /0 244 002  /0  /0 240  /0  /0  /0  /n  /0  /0  /0

0001160  /b  /0  /0  /0 004  /0  /0  /0 020  /0  /0  /0  /t  /0  /0  /0

0001200 003  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0   D 003  /0  /0

0001220 022  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0 001  /0  /0  /0

0001240  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001260  /0  /0  /0  /0 001  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001300 004  /0 361 377  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001320 003  /0 001  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001340 003  /0 003  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001360 003  /0 004  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001400 003  /0 005  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001420 003  /0  /a  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001440 003  /0 006  /0  /b  /0  /0  /0  /0  /0  /0  /0   +  /0  /0  /0

0001460 022  /0 001  /0  /r  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0  /0

0001500 020  /0  /0  /0  /0   t   e   s   t   .   c  /0   m   a   i   n

0001520  /0   p   u   t   s  /0  /0  /0 024  /0  /0  /0 001 005  /0  /0

0001540 031  /0  /0  /0 002  /t  /0  /0  /n

0001551

 

4.       链接(Linking:在成功编译之后,就进入了链接阶段。在这里涉及到一个重要的概念:函数库。重新查看这个小程序时,在这个程序中并没有定义“printf”的函数实现,且在预编译中包含进的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,Gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”,而这也就是链接的作用。

函数库一般分为静态库和动态库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a” 。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。GCC 在编译时默认使用动态库。完成了链接之后,GCC 就可以生成可执行文件。

 

执行以下命令生成可执行文件test

[root@localhost gccinfo]# gcc test.o -o test

同时也可以通过od命令产看其内容。

 

以上4个编译步骤可以一次完成,执行下面命令即可:

[root@localhost gccinfo]# gcc test.c -o test

编译程序时,gcc会自动帮你连接所有编译的文件名及标准函数库. 首先GCC会把所有的原始文件都转成目标文件,然后会自动调用linker 来连接相关文件名(事实上linker是个文件名为ld的程序,而不是gcc 本身提供的功能,我们可以说gccld的关系是相当密切的),GG同样 也知道标准函数库的位置,并且在调用ld时传入相关信息。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值