本篇为 OS Lab1 的实验报告,重点记录 Thinking 题作答、关键难点分析与实验体会。
一、实验目标与内容
- 从操作系统角度理解 MIPS 体系结构
- 掌握操作系统启动的基本流程
- 掌握 ELF 文件的结构和功能
- 完成 printk 函数的编写
二、Thinking
Thinking 1:
反汇编代码
objdump -d a.out # 反汇编 .text 节区 objdump -D a.out # 反汇编所有节区 objdump -d -M intel a.out # 使用 Intel 汇编语法 objdump -S a.out # 混合显示源代码与汇编(需 -g 编译)
查看文件结构
objdump -f a.out # 文件头信息(架构、入口地址等) objdump -h a.out # 节区头信息 objdump -x a.out # 所有头信息(等价于 -a -f -h -r -t)
符号与重定位信息
objdump -t a.out # 符号表 objdump -T lib.so # 动态符号表 objdump -r a.out # 重定位信息 objdump -R lib.so # 动态重定位信息
控制输出范围
objdump -d –start-address=0x400500 –stop-address=0x400530 a.out objdump -j .text -s a.out # 查看指定节区内容
Thinking 2:
因为是ELF64,自己的ELF32无法解析
1ELF 头:
2 Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
3 类别: ELF64
4 数据: 2 补码,小端序 (little endian)
5 Version: 1 (current)
6 OS/ABI: UNIX - System V
7 ABI 版本: 0
8 类型: DYN (Position-Independent Executable file)
9 系统架构: Advanced Micro Devices X86-64
10 版本: 0x1
11 入口点地址: 0x1180
12 程序头起点: 64 (bytes into file)
13 Start of section headers: 14488 (bytes into file)
14 标志: 0x0
15 Size of this header: 64 (bytes)
16 Size of program headers: 56 (bytes)
17 Number of program headers: 13
18 Size of section headers: 64 (bytes)
19 Number of section headers: 31
20 Section header string table index: 30
Thinking 3:
因为上电后BIOS会先启动,找到操作系统内核所在处,然后载入内存,内核本身不必位于上电复位地址,Bios本身可以充当一段跳转指令。
三、难点分析
readelf.c 里最容易错的是偏移计算。
要先用e_shoff找到节头表,再按e_shentsize一个个往后取,不然地址会读错。自己写的 readelf 不能解析 readelf 本身。
因为我们按 ELF32 写的,系统 readelf 一般是 ELF64,结构不一样,所以读不出来。kernel.lds 里
.text/.data/.bss的位置要放对。
这个不是随便填,位置不对可能编译过了但运行有问题。start.S 要先把栈指针设好,再跳到
mips_init。
栈没设好,后面的 C 函数调用就可能不正常。vprintfmt() 分支比较多。
要先识别%,再处理不同格式;有一个 case 漏掉就会输出不对。
四、实验体会
课下实验先仔细看 guidebook,跟着流程做会比较顺。
但课上实验基础部分写得更多,不只是会写代码,还要能说明代码行为。
这次在查找表名字符串表时,我更清楚了一个点:这是文件内偏移,基址应该选 binary,不是表名字符串所在表。
在 printk 实验里,过程被简化了不少。参数表调用和功能函数不用自己全写,重点在标识符识别和正确调用功能函数。
但课上实验更偏向把关键功能自己补完整,所以不能只复习课下流程,也要巩固那些课下没有手写的部分。