Lab1 实验报告
一、思考题
Thinking 1.1

答:
执行 gcc -E hello.c
后部分代码如下

执行 objdump -DS hello.o > test.txt
后main代码如下

执行 gcc hello.o -o hello
objdump -DS hello > test.txt
后main代码如下

执行 mips-linux-gnu-gcc -E hello.c
后部分代码如下
使用 MIPS
交叉编译器编译为 hello.o
文件
通过链接器获得可执行文件hello
Thinking 1.2

执行 readelf -h readelf
后结果
执行 readelf -h ./target/mos
后结果

执行readelf -h hello
后结果

思考:由于内核文件是大端存储,我们写的文件无法访问,而我们写的文件是小端存储,可以访问。
Thinking 1.3

答:
MIP体系结构启动时,启动入口地址为0xBFC00000
,位于kseg1地址段内,因此MMU将虚拟地址的高三位清零成为物理地址,其为0x1FC00000
,而该地址已经在硬件上确定位置,之后执行Bootoader,将Linux内核镜像拷贝到RAM中,此时因为Exercise 1.2中我们已在kernel.lds
中指定了各个节的加载位置,并且以Entry(_start)
指定了内核的入口,保证内核入口可被正确跳转到。
二、实验难点
1.理解指针对于ELF文件中段(Segments)和节(Sections)位置下数据的获取
针对这个问题,首先要对ELF的结构进行深入理解

若要读取某个section
中的数据,首先需要从ELF header
中找到节头表(section header
)以及文件头的偏移e_phoff
,将文件头地址与其相加即可获得节表的位置。还可以在文件头中获取节大小以及节数量从而通过指针移动遍历所有节。段的查找以及遍历与之相同。(PS:section
的增长方向与segment
相反)
2.理解printf()的实现逻辑
通过实验,我们可以知道printf()
的实现原理就是遍历字符串,如果遇到\0
或者%
就将之前的字符串打印,\0
则结束函数,%
则进行输出格式的判断,输出格式串为 %[flags][width][length]<specifier>
,判断后代入参数从而进行不同的输出。
三、心得体会
本次Lab主要收获在于掌握操作系统启动的流程、理解ELF文件的结构功能以及实现printf()
函数。
实验的额外收获在于掌握了如何在vscode上搭建跳板机,从而实现在vscode上完成实验,实现实验文件可视化以及掌握ssh连接逻辑()。