《程序员的自我修养》读书笔记-编译链接过程

准备

对于入门的hello world程序, 如下所示:

#include <stdio.h>
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 <stdio.h>
#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)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
程序员自我修养:链接,装载与库》是一本由林锐、郭晓东、郑蕾等人合著的计算机技术书籍,在该书中,作者从程序员的视角出发,对链接、装载与库等概念进行了深入的阐述和解析。 在计算机编程中,链接是指将各个源文件中的代码模块组合成一个可执行的程序的过程链接可以分为静态链接和动态链接两种方式。静态链接是在编译时将所有代码模块合并成一个独立的可执行文件,而动态链接是在运行时根据需要加载相应的代码模块。 装载是指将一个程序从磁盘上加载到内存中准备执行的过程。在装载过程中,操作系统会为程序分配内存空间,并将程序中的各个模块加载到相应的内存地址上。装载过程中还包括解析模块之间的引用关系,以及进行地址重定位等操作。 库是指一组可重用的代码模块,通过链接和装载的方式被程序调用。库可以分为静态库和动态库。静态库是在编译时将库的代码链接到程序中,使程序与库的代码合并为一个可执行文件。动态库则是在运行时通过动态链接的方式加载并调用。 《程序员自我修养:链接,装载与库》对于理解链接、装载和库的原理和机制具有极大的帮助。通过学习这些概念,程序员可以更好地优化代码结构和组织,提高程序的性能和可维护性。同时,了解链接、装载和库的工作原理也对于进行调试和故障排除具有重要意义。 总之,链接、装载与库是计算机编程中的重要概念,对于程序员来说掌握这些知识是非常必要的。《程序员自我修养:链接,装载与库》这本书提供了深入浅出的解释和实例,对于想要学习和掌握这些知识的程序员来说是一本非常有价值的参考书籍。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值