注:本文档为《从0学x86操作系统》课程配套的学习文档,提供相应的辅助学习资料和答疑勘误。 有关该课程的信息,请点击这里访问:https://study.163.com/provider/1017884735/index.htm 在阅读本文档时,如有疑问和建议,欢迎在下方留言或者直接联系我。
本课时主要介绍编译器具体如何安排工程生成的指令、数据在内存中的存储位置,并简要介绍gcc链接脚本的写法。
原理介绍
课程中通过分析工程的生成的反汇编文件和elf解析文件,展示了GCC工具链是如何安排代码、数据在内存中的存储,如下图所示。
具体而言,我们知道GCC工具链默认按.text, .rodata, .data, .bss存储代码和数据,并分析得出以下结论:
- .text:存储机器指令和代码
- .rodata:存储常量以及字符串本身
- .data:存储初始化的数据,全局的或者静态的
- .bss:存储未初始化的数据(即初始化为0),全局的或者静态的
- stack:存储局部变量和函数调用中返回地址等
- 相同类型的段会自动进行合并
当然,具体的细节会比上述的要复杂很多,在此我们只是得出一个初步地认识。在以后的课程中,还将会更深入其中的一些细节。我们也可以自己编写一个简单的链接脚本,来替代默认的存储配置。在链接脚本中,可以做更为复杂和灵活的设置。其语法结构为:
section { . = 虚拟地址; .text/.rodata/.data/.bss : { 目标文件(.text/.data/.bss/.data) /可使用通配符*/ }
}
扩展阅读
ARM开发中的RO, ZI, RW段
有的同学使用过arm公司的armcc工具链(如keil),其编译输出窗口中会提示RO=??, ZI=??, RW=??。
Total RO Size(Code + RO Data) 1008 ( 0.98kB) Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
这三种段和上面的类似,可以理解为相同类型的段换了个名字而已:
RO:即read-only,只读,对应于.text, .rodata,因为这两者一般是不可以修改的。
RW:即read-write,可读写,对应于.data
ZI:即zero …??,初始化为0,对应于.bss
参考资料
- GCC LD官方文档:https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html
- linker脚本(较易阅读):https://wiki.osdev.org/Linker_Scripts
- ARM Linker链接脚本:http://www.bravegnu.org/gnu-eprog/linker.html
- ld脚本编写:https://sourceware.org/binutils/docs/ld/