转自:
http://blog.csdn.net/elevenxjz/article/details/5951366
博主:记得以前考过这么一题,说汇编是一个什么过程。。。。好吧,当时正处于远去了汇编语言,黯淡了编译原理的阶段,脑海中一阵晃动纠结~~~
不扎实呀呀~~~
参考华清远见《嵌入式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
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 ""
3 # 1 ""
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):在这个阶段GCC把test.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 本身提供的功能,我们可以说gcc和ld的关系是相当密切的),GG同样 也知道标准函数库的位置,并且在调用ld时传入相关信息。