我们在使用gcc生成可执行程序的时候,一般是命令: gcc *.c, 生成可执行文件a.out
其实过程可以分为4个步骤,分别是预处理,编译,汇编和链接。下面以最基本的helloworld来简单了解一下编译的过程。
1.预编译
预编译又称为预处理,是做些代码文本的替换工作。
处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段,主要处理#开始的预编译指令。
gcc -E hello.c -o hello.i
生成的hello.i仍然是个文本文件
cat@lenovo:~/blog/0718$ ls
hello.c
cat@lenovo:~/blog/0718$ gcc -E hello.c -o hello.i
cat@lenovo:~/blog/0718$ file hello.i
hello.i: UTF-8 Unicode C program text
2.编译
把用高级程序设计语言书写的源程序,翻译成汇编语言
cat@lenovo:~/blog/0718$ ls
hello.c hello.i
cat@lenovo:~/blog/0718$ gcc -S hello.i
cat@lenovo:~/blog/0718$ ls
hello.c hello.i hello.s
cat@lenovo:~/blog/0718$ cat 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 puts
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",@progbits
3.汇编
这个过程把汇编语言翻译成机器语言
cat@lenovo:~/blog/0718$ ls
hello.c hello.i hello.s
cat@lenovo:~/blog/0718$ gcc -c hello.s
cat@lenovo:~/blog/0718$ ls
hello.c hello.i hello.o hello.s
cat@lenovo:~/blog/0718$ file hello.o
hello.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
4.链接
将生成的目标文件和其所依赖的库文件进行连接,生成一个可执行文件
cat@lenovo:~/blog/0718$ gcc hello.o
cat@lenovo:~/blog/0718$ ls
a.out hello.c hello.i hello.o hello.s
cat@lenovo:~/blog/0718$ ./a.out
hello world