csdn地址:《程序员的自我修养》读书笔记-编译链接过程
准备
对于入门的hello world程序, 如下所示:
#include
int main()
{
printf("hello world\n");
return 0;
}
在IDE中仅需点击一下运行既可看到程序的运行结果,而如果使用GCC编译,也非常简单,只需gcc hello.c即可生成目标文件a.out, 但其中隐藏了编译链接的基本步骤,分别为:预处理、编译、汇编和链接。通过
gcc --verbose hello.c -o a.out
可看到各步骤的流程。
预处理
预处理过程主要处理源码中以“#”开始的预编译指令, 比如“#include"、“define"等。通过预处理后的输出文件后缀为.i 或者.ii, 具体实现预处理过程的为预编译器cpp。若要查看预处理后的文件,可用:
gcc -E hello.c -o hello.i
或者:cpp hello.c > hello.i
- 主要处理规则:
1. 删除所有的#define, 并展开所有的宏定义;
2. 处理所有的条件预编译指令,如#if、#ifdef等;
3. 处理“#include"预编译指令;
4. 删除所有注释;
5. 添加行数和文件名标识;
- 举例说明:
例如定义常量 CONST_TEST,如下:
#include
#define CONST_TEST 5
int main()
{
printf("%d\n", CONST_TEST);
return 0;
}
在经过预处理后main函数变成如下:
int main()
{
printf("%d\n", 5);
return 0;
}
编译
编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析以及优化后生成相应的汇编代码文件。gcc命令如下:
gcc -S hello.i -o hello.s
或者:ccl hello.c
备注:对于c语言来说, 预处理和编译的实现程序为ccl, c++对应的程序为cclplus。
生成的hello.s文件为:
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str(%rip), %rdi
movl $0, -4(%rbp)
movb $0, %al
callq _printf
movl $1, %ecx
movl %eax, -8(%rbp) ## 4-byte Spill
movl %ecx, %eax
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "hello world\n"
.subsections_via_symbols
汇编
汇编过程主要是将汇编代码转变成机器可以执行的指令, 生成目标文件。gcc命令为:
gcc -c hello.s -o hello.o
或者:as hello.s -o hello.o
链接
通过汇编过程生成的目标文件并不能直接执行,其原因包括:某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数等, 而链接就是解决这些问题。链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够按操作系统装入执行的统一整体。链接命令为ld,对于上诉的hello wrold程序,可用:
ld -demangle -dynamic -arch x86_64 -macosx_version_min 10.12.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -o hello.out hello.o -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin/libclang_rt.osx.a
备注:测试环境为mac 10.12.3 (16D32)。