lab1实验报告
一、实验思考题
Thinking1.1
运行readelf
工具
readelf -h vmlinux
运行自己编写的readelf
./readelf vmlinux
注意到Data
中显示为big endian
,而当前我们完成的readelf
只能读取小端存储的文件,除非是上过机的readelf。所以在运行我们自己的./readelf
中显示段错误。
为了验证这一点,运行命令解析testELF
readelf -h testELF
可以发现,该文件为小端存储
Thinking1.2
为解决这个问题,先查看mmu.h
文件,通过这个文件可以发现,内核的起始地址为0x00000000
。
通过上文中readelf
命令来解析,得到入口地址。
也就是说main
函数存放在地址为0x80010000
的地方。
进入main
函数的方法是执行跳转指令jal
,跳转到指定的函数位置执行,并保存返回地址。
跨文件调用,需要先找到或者分配好每一个函数的地址,通过汇编代码的学习,函数的前后有一组压栈和弹栈的操作,可以保存函数当前的状态。
调用前设置传递的参数,例如保存在a0-a3
寄存器中
- 函数的开始,编译器减小
sp
指针的值,为栈分配空间,将需要保存的值存放在栈中 - 函数要返回时,编译器增加
sp
指针的值,释放栈空间,恢复之前保存的寄存器的值
调用结束,实现功能,或者得到函数返回。例如v0-v1
寄存器中的值。
二、实验难点图示
第一个难点在于ELF
文件的理解
-
怎样找到段头表入口
- 利用文件
binary
和已经存储的ehdr->e_shoff
找到地址
- 利用文件
-
如何利用段头表的结构体定义合理寻址
-
数组方式。
Nr * sh_entry_size
-
累加方式。$ \sum_1^{N_i} sh\_entry\_size $
大致思路一样,只在具体实现略有差异
-
第二个难点在于printf
函数实现
在之前的程序设计课上有过相关的练习,但当时只是非常简化的版本,具体实现也较为容易,而这次完成确有一定困难。
- 阅读工程代码
- 之前接触的不过是近百行的小程序,但本次阅读的代码和相关知识很多,需要建立工程的思路。
- 运用源码思维
- 首先需要理解每个参数有什么作用、每个代码段的执行逻辑
- 学习这种逻辑并续写
所以大多数时间都花在了阅读并理解相关的代码上,其实如果真正理解实现逻辑,需要动手填充的部分并不多。
三、体会与感想
通过本次实验,对于文件格式,makefile
操作有了更进一步的理解和认识。操作系统的启动是十分复杂的。硬件和软件之间存在着依赖的关系,想要透彻理解需要下苦功夫。
编译与链接,通过对于ELF
文件的理解和练习,能有更深刻的体会,多个文件如何生成单个可执行文件。
阅读代码能力,之前接触过的代码最多不过百行左右,并且主要是执行部分。在练习中需要阅读很多工程相关的代码,很多的宏定义、宏函数,以及更长的代码块,还需要在理解的基础之上补充相关逻辑部分,是很好的锻炼机会。
标签:文件,函数,代码,readelf,地址,lab1,理解,实验报告 From: https://www.cnblogs.com/ddl789/p/17219732.html