《程序员的自我修养》
《程序员的自我修养》这本书偏底层,来来回回读了有三四遍了,每一次都有新的收获,不过很快又会忘记,所以写下了这本书从17年12月份至今的全书的笔记,留作以后自己复习。
第二章:编译和链接
源代码生成可执行文件经过了几个步骤:
预编译 编译 汇编 链接
每个步骤做的事分别有
预编译 主要处理#号开头的预编译指令 比如宏定义#define 对源代码作简单的字符替换
#include将包含的文件插入到该指令的位置 删除注释
编译 对源代码进行扫描 生成一个一个的记号 然后用这些记号生成语法树 再根据语法树生成中间代码 比较典型的有 三地址码 形式是 Z = X op Y 然后用中间代码生成目标机器代码 也就是汇编指令
汇编 对汇编指令进行查表 翻译成0101的机器语言
链接 将所有的可重定位目标文件链接 生成可执行目标文件
首先
自己怎么验证这些知识点的过程
预编译 用gcc –E 指令处理文件后 查看生成的.i文件 发现#include指令包含的文件确实插入到了源代码种 源代码增大了许多 从200个字节增大到20kb
编译 用gcc –s 指令处理后 发现生成的.s文件 从20k变成了1.3k 确定是生成中间代码时优化了源代码 里面都是汇编代码
汇编 用gcc –c 指令处理后 发现生成的.o文件 从1.3k又增大到了2.2k 此时的文件叫做可重定位文件
56页开始
目标文件
elf文件 和 虚拟地址空间
elf虽然叫做可执行文件格式,可是不只是可执行文件(/bin/bash)用可执行文件格式存储
elf文件(可执行文件格式) 比如:.o /bin/bash文件 .so文件
.s 文件用file查看 叫做 ASCII text 文件
目标文件长什么样:
目标文件分段储存信息,
- 开头是一个elf头文件.,这个头文件描述了整个文件的文件属性,//不确定//和一个段表Section Table(描述各个段的数组,每个段在文件中的偏移位置)
- .text存放程序指令
3. .data段存放初始化了的全局变量或者静态局部变量
4. .bss段初始化为0或未初始化的全局变量和静态局部变量 但是.bss段其实没有内容,是个预留的位置(未初始化的全局变量会在*COM* 强符号与弱符号的问题)
除了这三个常用段 还有常见的有
.rodata段 只读数据段 如:字符串常量 全局const变量
.comment段 编译器版本信息 如:GCC:(GNU)4.8.5
.symtab段 Symbol Table 符号表
ELF Header
查看ElF Header 的数据结构 /usr/include/elf.h
a.out的文件魔数开头 0x01,0x07是个跳转指令
e_type:表示ELF文件类型,每个类型对应一个常量,系统通过这个判断(P74)
e_entry: Entry point address入口地址,规定eld程序的入口虚拟地址
e_shoff:Start of section header 段表在文件中的偏移
e_ehsize Size of this header ELF文件头本身的大小
e_shnum: Number of section headers 段表描述符数量 等于ELF文件拥有的段的数量
到71页 ELF头文件结构 需要看看32位下的入口点地址
段表:
底层的数据结构是数组,类型是 ELF32_Shdr,也定义在/usr/include/elf.h
描述了各个段的信息:每个段的 段名,段的长度,在文件中的偏移,读写权限
重定位表
.rela.text 段 类型为sh_type 表示是一个重定位表
符号:函数和变量统称为符号 Symbol
符号分为全局符号和局部符号
全局符号有两类:
1.定义在本目标文件的全局符号,可以被别的目标文件引用
2.外部符号, 引用了,却没有在本目标文件中定义的全局符号
局部符号:只在编译单元内部可见 如staic的变量
P87
c++有符号修饰的机制这是为了解决多态中函数名相同但是需要产生不同的符号名用于区分
不同的编译器可能会有不同的符号修饰方法这也是为什么不同编译器产生的.o文件可能不能正常链接
extern "c" { } 编译器会将大括号内的内容按照c语言处理也就是使c++中的符号名修饰机制失去作用
P92
弱符号和强符号
- inti; 这个是什么意思呢?有可能是定义也有可能是声明,对吧?那么怎么确定它是定义还是声明呢需要到链接的时候才能确定,因为只有到那个时候编译器才能看到所有的目标文件。那在链接之前呢,编译器会给这个符号i一个属性就是弱符号属性
- inti = 0;这个一定是定义,因为对i进行了初始化所以这个符号在编译阶段就可以确定了这就是强符号强符号在所有目标文件中只可以出现一次(这就是编译器报的重复定义的错误)
- extern inti; 这既不是强符号也不是弱符号,这是一个外部变量的引用,也就是变量声明。需要用编译器去查看一下,这产不产生符号。
强引用和弱引用
- 平时使用的声明就是强引用,强引用就是如果在所有的目标文件中没有找到符号的定义,链接时就会报错。
- 弱引用需要在引用前面加上 __attribute__((weakref))这个扩展关键字,即使没有找到弱引用的定义,链接时候也不会报错。但是运行的时候就会报错。弱引用一般是在库中使用,比如多线程pthread_create
__attribute__((weakref)) void foo();
If (foo) { foo(); }
------------------------------------------------------------------------------------------
预处理编译汇编链接
gcc–E hello.c –o hello.i
处理源文件中以#开头的预编译指令
编译:
把预处理玩的文件进行一系列词法分析(将源代码的字符序列分割成一系列记号),语法分析(产生语法树,表达式不合法,括号不匹配,表达式中缺少操作符,这些错误都是在这一步被发现的),语义分析(声明,类型的匹配,类型的转换)及生成汇编代码
链接:
把每个模块组装起来
分三步
- 地址和空间分配: (1)输出的可执行文件中的空间的分配
(2)装载后的虚拟地址中的虚拟地址空间的分配
计算出输出文件中的各个段的长度与位置并建立映射关系(相似段合并)
- 符号解析:
- 重定位: 将重定位表中需要重定位的外部符号进行重定位
转载于:https://www.cnblogs.com/hanhuihanhui/p/8651983.html
《程序员的自我修养》相关推荐
- ComeFuture英伽学院——2020年 全国大学生英语竞赛【C类初赛真题解析】(持续更新)
视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...
- ComeFuture英伽学院——2019年 全国大学生英语竞赛【C类初赛真题解析】大小作文——详细解析
视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...
- 信息学奥赛真题解析(玩具谜题)
玩具谜题(2016年信息学奥赛提高组真题) 题目描述 小南有一套可爱的玩具小人, 它们各有不同的职业.有一天, 这些玩具小人把小南的眼镜藏了起来.小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的 ...
- 信息学奥赛之初赛 第1轮 讲解(01-08课)
信息学奥赛之初赛讲解 01 计算机概述 系统基本结构 信息学奥赛之初赛讲解 01 计算机概述 系统基本结构_哔哩哔哩_bilibili 信息学奥赛之初赛讲解 02 软件系统 计算机语言 进制转换 信息 ...
- 信息学奥赛一本通习题答案(五)
最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...
- 信息学奥赛一本通习题答案(三)
最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...
- 信息学奥赛一本通 提高篇 第六部分 数学基础 相关的真题
第1章 快速幂 1875:[13NOIP提高组]转圈游戏 信息学奥赛一本通(C++版)在线评测系统 第2 章 素数 第 3 章 约数 第 4 章 同余问题 第 5 章 矩阵乘法 第 6 章 ...
- 信息学奥赛一本通题目代码(非题库)
为了完善自己学c++,很多人都去读相关文献,就比如<信息学奥赛一本通>,可又对题目无从下手,从今天开始,我将把书上的题目一 一的解析下来,可以做参考,如果有错,可以告诉我,将在下次解析里重 ...
- 信息学奥赛一本通(C++版) 刷题 记录
总目录详见:https://blog.csdn.net/mrcrack/article/details/86501716 信息学奥赛一本通(C++版) 刷题 记录 http://ybt.ssoier. ...
- 最近公共祖先三种算法详解 + 模板题 建议新手收藏 例题: 信息学奥赛一本通 祖孙询问 距离
首先什么是最近公共祖先?? 如图:红色节点的祖先为红色的1, 2, 3. 绿色节点的祖先为绿色的1, 2, 3, 4. 他们的最近公共祖先即他们最先相交的地方,如在上图中黄色的点就是他们的最近公共祖先 ...
最新文章
- 关于通过Sequential容器创建LeNet-5
- ICLR 2020将采用远程会议,首次在非洲办会可能就这样泡汤了
- stl-vector详解
- P3128 [USACO15DEC]Max Flow P
- Spring Boot 1.5.x新特性:动态修改日志级别
- 联想计算机不能进入系统桌面,联想电脑装系统,进不了PE桌面,怎么处理?
- ndroid中View.inflate()
- 在javascript使用EL表达式注意事项
- 关于QTTabBar的使用
- 高斯光束matlab 仿真,高斯光束的matlab仿真.docx
- 给群联PS3111/inic6081量产工具添加闪存颗粒支持
- java anon,试图找到泄漏!对于pmap来说,anon意味着什么?
- 百度云搭建微信公众平台服务器,微信大众开放平台开发03-百度BAE上搭建属于自己的微信公众平台 -JAVA,微信公众开放平台部署到百度云中BASE2.0,进行调试,木有钱买云服务器的亲们试试...
- [AndroidStudio]Building Apps with Over 64K Methods
- 安卓访客模式_如何设置Android访客模式以及为什么要这么做 | MOS86
- 英国《物理世界》杂志评选出世界十大物理学家
- BiometricPrompt之七 - Android R AuthBiometricView BiometricDialogView无法消失解决方案
- [爆笑网文][言论]《李毅:球迷骂我是因为我有威胁 谁让我踢得好呢》之幽默评论版(另附原文)
- 妙味课堂:一起学习jQuery源码【逐行分析jQuery源码的奥秘】(妙味课堂笔记)-- 框架接口(1-3)
- DFIG_Wind_Turbine:基于MATLAB/Simulink的双馈异步风力发电机仿真模型,控制方案采用矢量控制,电机的有功功率和无功功率由转子侧变换器控制