一 概述
编译过程分为四个步骤:预处理、编译、汇编、链接。
test.c
#include<stdio.h>
#define VALUE 10
int main(){
int i = 2;
if(i>1){
printf("value = %d",i); //test
}
return 0;
}
二 预处理
预处理过程中主要处理源文件中的 "#include" ,"#define"等预处理命令,主要完成的工作有:
- 删除#define,展开宏定义中的内容;
- 处理条件编译指令,预处理程序判断条件,根据条件修改源代码;
- 删除注释;
- 添加行号,以及文件明标识,便于调试。
- 删除"#include",插入相应的头文件;
预处理命令:g++ -E tese.c -o test.i
test.i中的部分代码
# 4 "test.c" //没有头文件和宏定义
int main(){
int i = 2;
if(i>1){
printf("value = %d",i); //没有test注释
}
return 0;
}
三 编译
编译后生成汇编代码,可以从test.i文件生成也可以从test.c文件直接生成。
g++ -S test.i -o test.s / g++ -S test.c -o test.s
test.s&test1.s
.file "test.c"
.text
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "value = %d\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
.LFB28:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $48, %rsp
.seh_stackalloc 48
.seh_endprologue
call __main
movl $2, -4(%rbp)
cmpl $1, -4(%rbp)
jle .L2
movl -4(%rbp), %eax
movl %eax, %edx
leaq .LC0(%rip), %rcx
call printf
.L2:
movl $0, %eax
addq $48, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0"
.def printf; .scl 2; .type 32; .endef
四 汇编
汇编过程会将汇编代码转化为机器指令,生成目标二进制文件。同样可以用任何一个前期文件开始执行汇编操作。
g++ -c test.c -o test.o / g++ -c test.i -o test1.o / g++ -c test.s -o test2.o
test.o&test1.o&test2.o(看不懂)
五 链接
链接过程会将机器指令链接成可执行文件。同样可以从前期文件(test.o文件除外)开始链接。
g++ -c test.c -o test.exe / g++ -c test.i -o test1.exe / g++ -c test.s -o test2.exe
六 执行
链接生成的可执行文件,进行执行,得到结果。
test / test.exe // test1 / test1.exe // test2 / test2.exe