Linux GCC编译C程序
Linux GCC编译C程序
一个c语言程序从源文件到生成可执行文件,编译器需要共经历4个步骤:
1) 预处理:把c文件中预处理命令扫描处理完毕,即对源代码文件中的文件包含(#include)、预编译语句(如宏定义#define等)进行分析,此时生成的文件仍然是可读的。
2) 编译:把预处理后的结果编译成汇编或者目标模块,即生成汇编语言文件,此时生成的文件仍然是可读的汇编文件。
3) 汇编:把编译出来的结果汇编成具体CPU上的目标代码模块,也即此时转换成具体的机器语言代码,此时生成的文件是不可读的非文本文件。
4) 连接:把多个目标代码模块连接生成一个大的目标模块,即将多个上面产生的机器代码文件(与其它的机器代码文件和库文件)汇集成一个可执行的二进制代码文件。
gcc作为c语言在Linux下很著名的编译软件,分别有如下option来支持4个步骤:
名称 gcc选项 英文名称 gcc调用的程序 示例
预处理 -E Pre-Processing cpp gcc -E test.c -o test.i
编译 -S Compiling ccl gcc -S test.i -o test.s
汇编 -c Assembling as gcc -c test.s -o test.o
连接 无 Linking ld gcc test.o -o test
说明:
gcc在编译c语言文件时,首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(#include)、预编译语句(如宏定义#define等)进行分析;其次调用ccl进行编译工作,将文件编译成汇编语言文件,此时文件依旧是可读的;之后调用as进行汇编工作,将具体的汇编语言文件编译成cpu可执行的目标代码,此时文件不可读了;当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,链接。在链接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时,该程序所调用到的库函数也从各自所在的库中链接到合适的地方。下面对上面4个过程做下分别的说明:
1、在预处理阶段,如果不用“-o”指定文件名,那么会默认将预处理结果输出到标准终端设备。
[root@dbbak tmp]# cat a.c
int main()
{
printf("shengtong test!\n");
}
[root@dbbak tmp]# gcc -E a.c
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "a.c"
int main()
{
printf("shengtong test!\n");
}
[root@dbbak tmp]# gcc -E a.c -o a.i
[root@dbbak tmp]# cat a.i
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "a.c"
int main()
{
printf("shengtong test!\n");
}
2、在编译阶段,如果不用“-o”指定文件名,那么默认会生成一个“*.s”的汇编语言文件。
[root@dbbak tmp]# gcc -S a.i
[root@dbbak tmp]# ls
a.c a.i a.s
[root@dbbak tmp]# gcc -S a.i -o a1.s
[root@dbbak tmp]# ls
a.c a.i a.s a1.s
[root@dbbak tmp]#
[root@dbbak tmp]# cat a.s
.file "a.c"
.section .rodata
.LC0:
.string "shengtong test!\n"
.text
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
subl $12, %esp
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-42)"
[root@dbbak tmp]# cat a1.s
.file "a.c"
.section .rodata
.LC0:
.string "shengtong test!\n"
.text
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
subl $12, %esp
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-42)"
3、在汇编阶段,如果不用“-o”指定文件名,那么默认会生成一个“*.o”的机器语言代码文件。
[root@dbbak tmp]# gcc -c a.s
[root@dbbak tmp]# ls
a.c a.i a.o a.s a1.s
[root@dbbak tmp]# gcc -c a1.s -o a1.o
[root@dbbak tmp]# ls
a.c a.i a.o a.s a1.o a1.s
[root@dbbak tmp]#
[root@dbbak tmp]# file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
[root@dbbak tmp]# file a1.o
a1.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
|
评论暂时关闭