目录
- 1 环境说明
- 2 gcc编译步骤
- 2.1 编辑
- 2.2 预处理
- 2.3 编译
- 2.4 汇编处理
- 2.5 链接
- 3 一步到位的方法
1 环境说明
- 系统:Windows
- 编译器:gcc
- 命令行工具:cmder (用系统自带的命令行工具也可以)
2 gcc编译步骤
# | 步骤名 | 生成文件 | 功能 |
1 | 编辑(Edit) |
| 进行编码工作 |
2 | 预处理(Pre-processing) |
| 将 |
3 | 编译(Compiling) |
| 将经过预处理之后的程序转换成特定汇编代码(assembly code)的过程 |
4 | 汇编处理(Assembling) |
| 将上一步的汇编代码转换成机器码(machine code),生成目标文件 |
5 | 链接(Linking) |
| 将多个目标文以及所需的库文件链接成最终的可执行文件(executable file) |
2.1 编辑
编写以下代码,命名文件名为test.c
:
#include<stdio.h>
int main() {
printf("Hello World!");
return 0;
}
2.2 预处理
预处理gcc指令如下:
gcc -E test.c -o test.i
- 参数
-E
- 执行编译预处理 - 参数
-o
- 指明输出文件的文件名
执行过后控制台没有任何输出,打开文件夹会发现生成了一个test.i
文件
可以发现生成的test.i
文件会比test.c
文件大得多,因为进行了大量的替换,test.i
文件可以通过记事本方式打开的,也可以输入指令type test.i
在控制台查看,由于文件内容很多,下面仅展示最后部分,可以发现末尾部分还是我们编写的源代码,而头文件#include<stdio.h>
进行了全部替换
2.3 编译
编译gcc指令如下:
gcc -S test.i -o test.s
- 参数
-S
- 编译指令 - 参数
-o
- 指明输出文件的文件名
执行过后控制台没有任何输出,打开文件夹会发现生成了一个test.s
文件
我们这里用指令type test.s
在控制台查看文件内容,可以发现程序被转换成了汇编代码
.file "test.c"
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "Hello World!\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
leaq .LC0(%rip), %rcx
call printf
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (tdm64-1) 4.9.2"
.def printf; .scl 2; .type 32; .endef
2.4 汇编处理
汇编处理gcc指令如下:
gcc -c test.s -o test.o
- 参数
-c
- 汇编转机器码 - 参数
-o
- 指明输出文件的文件名
执行过后控制台没有任何输出,打开文件夹会发现生成了一个test.o
文件
由于文件已经是机器码了,打开文件的话显然都是乱码了,用指令type test.o
在控制台查看文件内容如下:
2.5 链接
链接处理gcc指令如下:
gcc test.o -o test
- 参数
-o
- 指明输出文件的文件名
执行过后控制台没有任何输出,打开文件夹会发现生成了一个test.exe
文件
既然已经转换成了.exe
可执行文件,在Windows操作系统下可以直接执行,直接在控制台输入test
,执行结果如下:
可以发现最后输出了Hello World!
那么整个过程就结束了
3 一步到位的方法
直接可以从.c
文件到.exe
可执行文件,这里就不演示了
gcc test.c -o test