专栏首页xcywt《程序员的自我修养》第二章学习笔记

《程序员的自我修养》第二章学习笔记

第二章 编译和链接

2.1被隐藏了的过程

我们知道,一个程序由源代码到可执行文件往往由这几步构成:

预处理(Prepressing)-> 编译(Compilation)-> 汇编(Assembly)-> 链接(Linking)。

如图所示,

2.1.1预编译 

#include<stdio.h>

int main(void)
{
  printf("Hello World\n");
  return 0;          
}

    如上述文件hello.c,  gcc -E hello.c -o hello.i

    预编译过程主要处理哪些源代码文件中的以 "#" 开始的预编译指令,比如 #include,#define 等,主要处理规则如下:

  1. 将所有的#define删除,并且展开所有的宏定义。

  2. 处理所有的预编译指令,比如 "#if" "#ifdef" "#elif" "#else" "#endif"等。

  3. 处理"#include"预编译指令,将被包含的文件插入到该预编译的位置。注意:这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。

  4. 删除所有的注释 "//"  ''/* */"。

  5. 添加行号和文件名标识,比如#2"hello.c"2,以便于编译时编译器产生调试用的符号信息及用于编译时产生编译错误或警告时能够显示行号

  6. 保留所有的#pragma编译器指令,因为编译器需要用到它们。

  经过预编译后的.i文件不包含任何宏定义(所有的宏都展开了),被包含的文件也被插入到.i文件中。

  参考文献《程序员的自我修养--链接、装载与库》 P39

2.1.2编译 详情参考2.2

1,现在版本的GCC把预编译和编译合并成了一个步骤,使用一个叫做ccl的程序来完成这两个步骤。

2,gcc只是一些后台程序的包装,它会根据不同的参数要求去调用预编译程序ccl,汇编器as,链接器ld。

2.1.3汇编

1,汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。

2,所以汇编器的汇编过程相对于编译器来讲比较简单,它没有复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了。

3,经过预编译、编译和汇编直接输出目标文件(Object File)。

4,可调用汇编器as来完成,  as hello.s –o hello.o

5,或者 gcc –c hello.s –o hello.o

6,也可以一步到位  gcc –c hello.c –o hello.o

2.1.4链接

2.2编译器做了什么  参考如下

http://www.cnblogs.com/xcywt/p/4902789.html

2.3链接器的年龄比编译器长

2.4模块拼装---静态链接

  1,  人们把每个源代码模块独立编译,然后按照需要将它们“组装”起来,这个组装的过程就是链接(Linking)。

  2,  链接的主要内容就是:把各个模块之间相互引用的部分都处理好,使得各个模块之间能够正确的衔接。

  3,  从原理上说,链接器的工作无非就是把一些指令对其他符号地址的引用加以修正。

  4,  链接过程主要包括了:地址和空间分配(Address and Storage Allocation),符号决议(Symbol Resolution)和重定位(Relocation)。

  5,  最基本的静态链接如下图所示,源文件经过编译成目标文件(*.o /  *.obj),目标文件和库一起链接最终形成可执行文件。

  6,  假如main.c用到了另一个模块fun.c中的food()函数。

    (1)编译mian.c时并不知道foo()的地址,所以暂时把这些调用foo()的指令的目标地址搁置。

    (2)链接器会根据所引用的符号foo,自动去相应的fun.c模块查找foo的地址。

    (3)然后将main.c中所有用到foo的指令重新修正,让它们的目标地址为真正的foo函数的地址。

  7,  地址修正的过程也叫重定位(Relocation)。

  8,  每个要被修正的地方叫一个重定位入口(Relocation Entry)。

参考文献《程序员的自我修养--链接、装载与库》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 关于C++编译链接和模板函数

    一,关于编译链接 编译指的的把编译单元生成目标文件的过程 链接是把目标文件链接到一起的过程 编译单元:可以认为是一个.c或者.cpp文件。每个编译单元经过预...

    xcywt
  • 前三章 man手册 查看文件

    1 – 3章 1.1 man手册: 分1 - 9个区域,可以认为是一个一个小节 把man手册理解为一本书 第一节:可执行程序或shell命令 第二节:系统调用 ...

    xcywt
  • 《Linux命令行与shell脚本编程大全》 第五章理解shell

    5.1 1. cat /etc/passwd 可以查看每个用户自己的默认的shell程序。 2.默认的交互shell会在用户登录某个虚拟控制台终端时启动。 不过...

    xcywt
  • 为什么有些程序员不愿意缩进代码?

    作为已经写了十几年代码的老程序员,虽然在编写代码的时候大部分情况还是遵循编码规范,但在这基础上会展示自己一些特性,有些程序员不喜欢缩进代码也是源于此,如同一个人...

    程序员互动联盟
  • LLVM + Clang + Libcxx + Libcxxabi 工具链编译

    LLVM和Clang工具链的生成配置文件写得比较搓,所以略微麻烦,另外这个脚本没有经过多环境测试,不保证在其他Linux发行版里正常使用。

    owent
  • 程序生成之编译、链接、加载浅析

    程序生成之编译、链接、加载浅析 最近笔者看论文烦得慌,便又重新拾起之前没有完全完成的交叉编译,准备在网上找资料,好好研究一下。 讲道理,笔者其实对编译链接的...

    剑影啸清寒
  • 老师木讲架构:深度学习平台技术演进

    新智元推荐 来源:OneFlow 【新智元导读】近日,袁进辉(老师木)代表OneFlow团队在全球互联网架构大会上海站做了《深度学习平台技术演进》的报告。报告包...

    企鹅号小编
  • 笔记 | GWAS 操作流程2-4:哈温平衡检验

    邓飞
  • iOS开发-视图渲染与性能优化

    前言 关于iOS的视图渲染流程,以及性能优化的建议。 源于WWDC视频。 我假设你是一个这样的开发者: 了解OpenGL ES; 了解view hierar...

    落影
  • 创建局部模型视图

    当模型中的表数量过多,导致关联变得复杂,不利于用户分析和理解表关系,而旧版Power BI中只提供这一种模型全局视图。

    公众号PowerBI大师

扫码关注云+社区

领取腾讯云代金券