Linux调试私房菜(四)揭开链接器的面纱、汇编语言的内嵌编程
七、揭开链接器的面纱(上)
1. 问题
源文件被编译后生成目标文件,这些目标文件如何生存最终的可执行程序?
2. 链接器的意义
链接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接。
3. 目标文件的秘密
- 各个段没有具体的起始地址,只有段大小信息
- 各个标识符没有实际地址,只有段中的相对地址
- 段和标识符的实际地址需要链接器具体确定
4. 链接器的工作内容
- 将目标文件和库文件整合为最终的可执行程序
- 合并各个目标文件中的段( .text, .data, .bss )
- 确定各个段和段中标识符的最终地址(重定位)
- 链接前后对比
5. 问题
main()函数是第一个被调用执行的函数吗?
6. 默认情况下( gcc )
- 程序加载后,_start()是第一个被调用执行的函数
- _start()函数准备好参数后立即调用__libc_start_main()函数
- __libc_start_main()初始化运行环境后调用main()函数执行
- _start()函数的入口地址就是代码段( .text )的起始地址!
7. __libc_start_main()函数的作用
- 调用__libc_csu_init()函数(完成必要的初始化操作)
- 启动程序的第一个线程(主线程),main()为线程入口
- 注册__libc_csu_fini()函数(程序运行终止时被调用)
8. 程序的启动过程
9. 自定义程序入口函数
- gcc提供-e选项用于在链接时指定入口函数
- 自定义入口函数时必须使用-nostartfiles选项进行链接
10. 思考
链接选项-nostartfiles的意义是什么?
链接时不要使用标准的系统启动文件。标准的系统库通常使用,除非使用-nostdlib或-nodefaultlibs。
八、揭开链接器的面纱(中)
1. 思考
链接器根据什么原则完成具体的工作?
2. 链接脚本的概念和意义
- 链接脚本用于描述链接器处理目标文件和库文件的方式
- 合并各个目标文件中的段
- 重定位各个段的起始地址
- 重定位各个符号的最终地址
3. 链接脚本的本质
4. 链接脚本初探( Round 1 )
5. 注意事项
- 各个段的链接地址必须符合具体平台的规范
- 链接脚本中能够直接定义标识符(源代码的变量)并指定存储地址
- 链接脚本中能够指定源代码中标识符的存储地址
在Linux中,进程代码段(.text)的合法起始地址为[0x08048000,0x08049000]
6. 编程实验:链接脚本初体验
8-1.lds
7. MEMORY命令
- 默认情况下
- 链接器认为程序应该加载进入同一个存诸空间
- 嵌入式系统中(可能不存在MMU)
- 如果存在多个存储空间,必须使用MEMORY 进行存储区域定义
8. MEMORY命令的使用( Round 2 )
9. MEMORY命令的属性定义
10. ENTRY命令指定入口点( Round 3 )
11. 编程实验:链接脚本指定入口函数
8-2.Ids
查看默认的链接脚本 ld --verbose > default.lds
默认进入 _start()
12. 小结
- 链接器根据链接脚本中的描述完成具体的工作
- 链接脚本用于指定各个段的地址和标识符的地址
- SECTIONS命令确定可执行程序中的段信息
- MEMORY命令对存储区域进行重定义
- ENTRY命令指定可执行程序的入口函数
九、汇编语言的内嵌编程
1. C 语言中的内嵌汇编
内嵌汇编的语法格式:
2. 内嵌汇编示例
- mov 类似于 赋值操作符
- 占位符 %1 %0 需要被后面的参数所替换。(%0 ==>result)
- asm … ==> result = input;
3. 编译器做了什么?
- 将result关联到某个适合的寄存器
- 将input关联到另一个适合的寄存器
- 通过通用寄存器间接操作变量
= 限制符 意味着后面是输出参数
4. 常用限制符的说明
5. 编程实验:内嵌汇编初体验
9-1.c
6. 问题
如何在不使用printf()的情况下打印字符串?
7. 通过INT 80H使用内核服务
- INT指令用于使用Linux内核服务(中断指令)
- 80H是一个中断向量号,用于执行系统调用
- 如何指定具体的系统调用(如∶sys_write )以及调用参数?
- 通过寄存器指定具体的系统调用及参数。
8. INT 80H使用示例一
限制符r 让编译器决定用什么寄存器与s和l关联,但是不能使用保留列表的寄存器。
9. INT 80H使用示例二
10. 注意事项
- 嵌入汇编时,除汇编模板外,其余参数可以全部省略
- 当省略的参数在中间时,对应分隔符":"不可省略
- 当省略保留列表时,对应分隔符":"可省略
- 当省略可选参数时,寄存器前使用单个%作为前缀
- 当存在可选参数时,寄存器前使用两个%作为前缀
11. 编程实验:深入体验内嵌汇编
打印刚退出进程的进程码
echo $?
12. 小结
- C 程序中支持直接嵌入汇编语言进行编程
- 通过寄存器到变量的关联完成汇编到C语言的交互
- 内嵌汇编代码时,通过占位符指定交互的变量
- 限制符指示编译器将适合的寄存器关联到变量
- 通过内嵌汇编能够直接使用系统服务
十、揭开链接器的面纱(下)
1. 课程实验(模拟嵌入式开发)
- 编写一个"体积受限"的可执行程序
- 通过makefile完成代码编译
- 运行后在屏幕上打印"D.T.Software"
2. 深度分析
3. 解决方案设计
- 通过内嵌汇编自定义打印函数和退出函数( INT 80H )
- 通过链接脚本自定义入口函数(不依赖任何库和GCC内置功能)
- 删除可执行程序中的无用信息(无用段信息,调试信息,等)
4. 打印函数设计
5. 退出函数设计
6. 链接脚本设计
.rodate和.text都是只读属性,放在一起达到减少段的目的。
.rodate只读数据区
7. 最后的准备(一)
- ld命令
- GNU的链接器,将目标文件链接为可执行程序
- GCC编译器集中的一员,重要的幕后工作者
- ld -static
- -static表示ld使用静态链接的方式来产生最终程序,而不是默认的动态链接方式
8. 最后的准备(二)
- - gcc -fno-builtin
- -fno-builtin参数用于关闭GCC内置函数的功能
GCC提供了很多内置函数(Built-in Function),它会把一些常用的C库函数替换成编译器的内置函数,以达到优化的目的。
9. 编程实验:模拟嵌入式开发
program.out
10. 小结
- 对于资源受限的嵌入式设备,需要考虑可执行程序的大小
- 通过内嵌汇编直接使用系统服务能够避开相关库的使用
- 可以通过如下方法控制可执行程序的体积大小
- 最小化库的使用(必要情兄下考虑自己实现相关函数)
- 自定义链接脚本,删除无用段信息
Linux调试私房菜(四)揭开链接器的面纱、汇编语言的内嵌编程相关推荐
- Linux中ELF格式 可执行文件+动态链接器 的加载
两种加载方式 (1)加载可执行文件,通过PT_INTERP加载动态链接器 (2)直接加载动态链接器,再由其加载可执行文件 On a typical ELF system such as Linux, ...
- linux动态可执行文件,Linux中ELF格式 可执行文件+动态链接器 的加载
两种加载方式 (1)加载可执行文件,通过PT_INTERP加载动态链接器 (2)直接加载动态链接器,再由其加载可执行文件 On a typical ELF system such as Linux, ...
- Linux开发常见问题:GCC:链接器输入文件未使用,因为链接尚未完成
问:我在Linux中运行一个make文件去编译C语言代码,然后得到了如下的错误信息: gcc -Wall -fPIC -DSOLARIS -DXP_UNIX -DMCC_HTTPD -D_ ...
- Linux常用命令介绍(20个)——《鸟哥的Linux的私房菜》
ls [选项] [目录名] -a, -l 列出当前目录下的所有文件和目录 -a 所有文件,包含以点开头的隐藏文件和目录.一个点代表当前目录,两个点代表上一层目录. -l 列出文件和目录的详细信息:包含 ...
- linux鸟叔私房菜读后感,鸟叔的Linux私房菜 读书笔记 第一章
目录dom 硬盘数学 第一章 计算机概论 知识点总结 计算机的定义为:接受使用者输入指令与资料,经由中央处理器的数学与逻辑单元运算处理后,以产生或储存成有用的资讯:程序 电脑的五大单元包括:输入单元. ...
- VLC多媒体播放器将字幕srt等 内嵌在视频中且能合并到视频,保存为带字幕的新视频 自媒作首选工具
VLC 是一款自由.开源的跨平台多媒体播放器,可播放大多数多媒体文件,以及 DVD.音频 CD.VCD 及各类流媒体协议.可以说是一款万能的多媒体播放器. 官方网站:http://www.videol ...
- vue打开其他项目的页面/打开外部链接,window模态框或内嵌在项目里
写这篇文章的时候心情很emo,希望自己更强大吧 在项目里通过点击列表当前行,拿到每行的id之后,跳转到新页面打开外链或者以window模态框的形式在当前页打开,并且叉掉后不影响原来的页面. 一:在项目 ...
- 《鸟哥的linux私房菜-服务器篇 第三版》 RHCA亲授
经典再现,<鸟哥的linux私房菜-服务 器篇(第三版)>远程班隆重推出! 鸟哥的linux的私房菜是linux教材中的 经典中的经典!是学习linux的绝佳资 料! 上课时间: 周一到周 ...
- 使用gcc编译和链接C语言程序,用GCC编译链接程序--编译链接器GCC常用功能(菜鸟级)...
转载自:http://daimajishu.iteye.com/blog/1089740 对gcc认识的一篇文章,就转载了,截取了自己感兴趣部分. 一,GCC编译器简介 虽然我们称Gcc是C语言的编译 ...
最新文章
- ROS中launch文件使用笔记
- 阿里云服务器 安全狗外部访问mysql_阿里云linux/centos服务器安全狗安装
- pom.xml设置mysql连接_maven工程配置pom.xml实现mybatis的访问数据库操作
- Remove Duplicates from Sorted List
- 别再用假任务做小样本学习实验了!来试试这个全新基准数据集
- HTML rel 属性
- 新书《深入理解Kafka:核心设计与实践原理》上架,感谢支持~
- 计算机考题中有关反码的考题,2019陕西信合招聘笔试模拟试题-计算机知识8
- 一文搞懂List 、ListObject、List?的区别以及? extends T与? super T的区别
- golang 捕获堆栈信息_一篇文章教你如何捕获前端错误
- word是多线程的程序_线程的基本概念,实现多线程的四种基本方式
- Java中的Object 类的常见方法
- element-ui 引用阿里云矢量图不显示图标,显示的为小方框
- 大数据早报:极课大数据获得1亿元融资 美科学家利用机器学习挖出人们背后的自杀行为(11.1)
- c语言的条件运算符,条件运算符c语言
- 标题怎样选择适合自己的导图结构
- 圆圈怎么用html实现,如何利用css实现圆形效果?
- oracle中skimmer的意思,skimmer to是什么意思
- 在Python中使用StanfordOpenIE
- android studio appt2,一步一坑学android之禁用Appt2(andriod studio3.0)