一.链接器上

链接器的意义--链接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接 A.目标文件的秘密 1.各个段没有具体的起始地址,只有段大小信息 2.各个标识符没有实际地址,只有段中的相对地址 3.段和标识符的实际地址需要链接器具体确定 链接器的工作内容--将目标文件和库文件合为最终的可执行程序 1.合并各个目标文件中的段(.text .data .bss) 2.确定各个段和段中标识符的最终地址(重定位) 运行的示例 根据之前一篇博客中的开发中的工具可以知道,同时使用nm命令可以看到标出红线的都处在段标识U(未定义的标识中) 而在对test.out文件进行nm命令后 可以看到之前未被定义的标识都处在相对于的标识段 Q:main()函数是第一个被调用执行的函数吗? 默认情况下(gcc) 1.程序加载后,_start()是第一个被调用执行的函数 2._start()函数准备好参数后立即调用_libc_start_main()函数 3._libc_start_main()初始化运行环境后调用main()函数执行 示例及说明 该示例就是通过简单的一段程序来对main函数是否是第一个被调用执行的函数,通过上篇博客中的反编译命令objdump使其生成result.txt文件来对汇编语言进行查看 可以看出对main进行查找时找到其地址值,然后将其地址值进行查找,发现在_start()函数中,此时进行的操作时将其地址值压入堆空间中,可以看到在之后对_libc_start_main()函数进行了调用 _libc_start_main()函数的作用 1.调用_libc_csu_init()函数(完成必要的初始化操作) 2.启动程序的第一个线程(主线程),main()为线程入口 3.注册_libc_csu_fini()函数(程序运行终止时被调用)

Q:链接器根据什么原则完成具体工作? 链接脚本的概念和意义 1.链接脚本用于描述链接器处理目标文件和库文件的方式‘ a.合并各个目标文件 b.重定位各个段的起始地址 c.重定位各个符号的最终地址 示例 上面的两段程序分别为简单的输出程序和脚本程序,运行的结果如图所示 发现在脚本语言中,出现了段错误的问题 注意事项: 1.各个段的链接地址必须符合具体平台的规范 2.链接脚本中能够直接定义标识符并指定存储地址 3.链接脚本中能够指定源代码中标识符的存储地址 运行objdump -h命令查看目标文件中的详细段信息 由该结果可以看出,出现段错误的原因,对其进行修改即可

**二.C语言在的内嵌汇编

A.内嵌汇编的语法格式 ** 简单示例: ** 在运行了反编译objdump -S 命令后可以看到红线标出的寄存器的关联和动作**

编译器的动作: 1.将result关联到某个适合的寄存器 2.将input关联到另一个适合的寄存器 3.通过寄存器间接操作变量 常用的限制符的说明

三 链接器下

课程实验 1.编写一个体积受限的可执行程序 2.通过makefile完成代码编译 3.运行后在屏幕打印数据 解决方案设计 1.通过内嵌汇编定义打印函数和退出函数(INT 80H) 2.通过链接脚本自定义入口函数(不依赖任何库和GCC内置功能) 3.删除可执行程序中的无用信息(无用段信息,调试信息,等) 工具 1.ld命令 a.GNU的链接器,将目标文件链接为可执行程序 b.GCC编译器集中的一员,重要的幕后工作者 2.ld -static a.-static表示ld使用静态链接的方式来产生最终程序,而不是默认的动态链接方式 3.gcc -fno-builtin -fno-builtin参数用于关闭GCC内置函数的功能 示例及运行结果 运行的结果如图所示 小结: 1.链接器根据链接脚本中的描述完成具体的工作 2.链接脚本用于指定各个段的地址和标识符的地址 3.SECTIONS命令确定可执行程序中的段信息 4.MEMORY命令对存储区域进行重定义 5.ENTRY命令指定可执行程序的入口函数 6.C语言中支持直接嵌入汇编语言进行编程 7.通过寄存器到变量的关联完成汇编到c语言的交互 8.内嵌汇编代码时,通过占位符指定交互的变量 9.限制符指示编译器将适合的寄存器关联到变量 10.通过内嵌汇编能够直接使用系统服务 11.对于资源受限的嵌入式设备,需要考虑可执行程序的大小 12.通过内嵌汇编直接使用系统服务能够避开相关库的使用