lab1实验报告

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文件的理解和练习,能有更深刻的体会,多个文件如何生成单个可执行文件。

阅读代码能力,之前接触过的代码最多不过百行左右,并且主要是执行部分。在练习中需要阅读很多工程相关的代码,很多的宏定义、宏函数,以及更长的代码块,还需要在理解的基础之上补充相关逻辑部分,是很好的锻炼机会。

posted @ 2023-03-15 19:41  Jareth  阅读(48)  评论(0)    收藏  举报