gcc 编译 汇编 链接
要想研究使用 gcc, gcc-multilib 这个包是一定要安装的, 它允许通过 -m32 和 -m64 选项来选择生成 32 位或者 64 的 ELF 文件.
我们知道程序的默认起点是 _start, 该函数做了一些未知/初始化的工作, 然后调用 main 函数, 如果 main 函数返回, 则由 _start 函数销毁进程.
我们可以使用 -e<symbol> 来重新设置该入口点.

观察上面的程序, 无论在32位下还是64位下均出现错误, 是什么原因?
没错, 就是因为没有销毁进程, 导致 ret(q) 指令(x86-64)继续执行, 该指令从调用者栈帧中取指令地址, 导致 main 函数返回到未知的内存地址取指令, 可能这个内存地址无法访问, 当然, 即使成功取址, 也极可能是无效的指令, 导致崩溃. 这件事告诉我们: 有些函数是不能返回的(实际上是计算机指令必须严格有序地按人类设计执行, 差之毫厘, 谬之千里).

编译
cpp 预处理, gcc -S 生成特定体系结构的汇编代码, 这个过程称为编译.
参数主要配置头文件搜索路径, 选择体系结构(-m32 -m64), 生成位置无关代码(-fPIC, 共享库必须要使用位置无关的目标文件, 而不是可重定位目标文件, 共享库不能重定位, 因为不知道, 也不能假设共享库的加载位置.)
汇编
as. 识别汇编代码, 生成可重定位或位置无关的目标文件, 什么区别? 毕竟复杂, 一言难弊.
链接
组织各目标文件, 生成可执行文件或共享库, 修改需要重定位的指令, 使其地址从0x0变为对应的线性地址, 共享库基本使用偏移寻址, 对外部符号的访问则采取 PLT 技术, 该技术使用成为 GOT 的偏移表, GOT 是运行时数据.
运行
现在我们有必要来研究一下什么是 "位置无关目标文件" 了

现在我们正常编译为 a.s, 查看之:

加上 -fPIC 选项, 编译为 b.s, 查看之:

使用 diff 查看差异:

编译后的目标文件具有显著差异:

请看一下汇编代码:

可见, 涉及地址的指令均需要链接器"细细商榷", 我们再看可执行文件:


想也知道, 直接寻址比偏移寻址快些, 这项技术主要用于共享库.
盗了一张图, 惊天大秘密:


图片来源:
https://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/
本文皆小儿之见, 文思迂腐, 切莫计较.
gcc 编译 汇编 链接的更多相关文章
- GCC编译和链接过程
GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分.GCC原本作为GNU操作 ...
- Linux | GCC如何实现代码编译&&汇编&&链接过程
正文: 每次我们程序员所写的 代码 是给程序员看的呢?还是给电脑看的?其实我们所写的代码只是我们程序员之间交流的一样特殊语言,电脑是看不懂的.那么我们如何实现人机交流呢?这就不得不请出我们我们今天 ...
- GCC编译和链接多个文件(包括源文件、目标文件、汇编文件等)
编译多个源代码文件会生成多个目标文件,每个目标文件都包含一个源文件的机器码和相关数据的符号表.除非使用-c选项指示 GCC 只编译不链接,否则 GCC 会使用临时文件作为目标文件输出: $ gcc - ...
- C语言预处理 编译 汇编 链接四个阶段
c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接. 编译过程 编译过程又可以分成两个阶段:编译和会汇编. 编译 编译是读取源程序(字符流),对之进行词法和语法的分析,将高 ...
- C/C++程序编译流程(预处理->编译->汇编->链接)
程序的基本流程如图: 1. 预处理 预处理相当于根据预处理指令组装新的C/C++程序.经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内 ...
- gcc编译动态和静态链接库
我们通常把一些公用函数制作成函数库,供其它程序使用.函数库分为静态库和动态库两种.静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.动态库在程序编译时并不会被连接到目标代码中,而是 ...
- gcc 编译和链接
1.现在对两个文件生成可执行文件 //thanks.c #include <stdio.h> int main(void) { printf("Hello World\n&quo ...
- gcc编译 汇编 选项
gcc生成main.out的步骤分解:<blockquote>main.c-----(-S 编译)-------->main.s-------(-c 汇编)------->ma ...
- GCC编译动态和静态链接库例子
我们通常把一些公用函数制作成函数库,供其它程序使用.函数库分为静态库和动态库两种.静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.动态库在程序编译时并不会被连接到目标代码中,而是 ...
随机推荐
- 自学华为IoT物联网_12 Huawei LiteOS基础架构
点击返回自学华为IoT物流网 自学华为IoT物联网_12 Huawei LiteOS基础架构 一.1个Huawei LiteOS Kernel 1.1 huawei LiteOS Kernel基本框架 ...
- emwin之自绘制 BUTTON 图形的一些问题
@2018-11-8 [小记] [需求] 官方只提供圆角矩形图形,其他图形及颜色需求则要自己实现 [注意] 通过回调函数自实现的图形绘制存在该回调函数一直被调用的现象,而非像窗口回调函数中 BUTTO ...
- hdu 4300 Clairewd’s message(扩展kmp)
Problem Description Clairewd is a member of FBI. After several years concealing in BUPT, she interce ...
- A1137. Final Grading
For a student taking the online course "Data Structures" on China University MOOC (http:// ...
- (转)你应该知道的RPC原理
背景:对于项目中的RPC框架,仅仅停留在使用层面,对于其底层的实现原理不是很清楚.这样的后果是很危险的,对于面试官来说,跟不知道这个东西一样. 转载自:https://www.cnblogs.com/ ...
- 第三十八篇-logcat的使用
很多時候,程序有问题时都需要debug,一般会设置几个信息点,查看程序是否运行,之前学过Toast,可以广播,但是终归是不太方便,今天学习一下logcat的用法. logcat里面是一些日志,内容太多 ...
- 如何计算Java对象所占内存的大小
[ 简单总结: 随便一个java项目,引入jar包: lucene-core-4.0.0.jar 如果是 maven项目,直接用如下依赖: <dependency> <groupId ...
- 第四节,Neural Networks and Deep Learning 一书小节(上)
最近花了半个多月把Mchiael Nielsen所写的Neural Networks and Deep Learning这本书看了一遍,受益匪浅. 该书英文原版地址地址:http://neuralne ...
- 彻底删除与安装MySQL
一.下载msi安装版:https://dev.mysql.com/downloads/mysql/ 二.安装前一定要彻底删除已有的MySQL:(从未安装过,忽略此步) 1.计算机处右键快捷菜单,管理, ...
- JavaSE_List&Array_Java1.7
这里简单写了下List和Array的相互转换 package cn.rocker.collection.list; import org.junit.Test; import java.util.Ar ...