ucore lab1 实验报告(基于实验楼的在线环境)

练习1:理解通过make生成执行文件的过程。

  1. 操作系统镜像文件ucore.img是如何一步一步生成的?(需要比较详细的解释Makefile中每一条相关命令和命令参数的含义,以及说明命令导致的结果)
  2. 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?

答:

(1)使用make “V=" 查看make执行了那些命令。

可以看到ucore.img是由bin/bootblock和bin/kernel构成的。其中第一个扇区放的是bin/bootblock,之后扇区存放bin/kernel。
在这里插入图片描述

dd命令的相关参数:

  • if代表输入文件。如果不指定if,默认就会从stdin中读取输入。
  • of代表输出文件。如果不指定of,默认就会将stdout作为默认输出。
  • count代表被复制的块数。
  • /dev/zero是一个字符设备,会不断返回0值字节(\0)。
  • seek代表一开始输出时,跳过指定的区块数。
  • conv=notrunc的功能是,写入文件时防止被截断。

Makefile中的相关命令:
在这里插入图片描述

bin/bootblock是由obj/bootblock.o 的复制,并使用tools/sign.o优化后的结果,该部分在make “V="结果中找不到,因为Makefile中相关命令前面设置了不显示,我们可以在Makefile中找到相关命令,并将其显示。obj/bootblock.o 由bootasm.o,bootmain.o 连接成的
在这里插入图片描述在这里插入图片描述

/bin/kernel是由kern目录下的所有文件,编译成.o文件后,连接起来的。

在这里插入图片描述
在这里插入图片描述

而其他.o文件的形成过程,都和下图类似。
在这里插入图片描述
(2) 查看tools目录下的sign.c文件,阅读其中代码得知一个被系统认为是符合规范的硬盘主引导扇区的特征为最后两个字节的数据是0x55和0xAA。
在这里插入图片描述

练习2: 使用qemu执行并调试lab1中的软件。

  1. 从CPU加电后执行的第一条指令开始,单步跟踪BIOS的执行。
  2. 在初始化位置0x7c00设置实地址断点,测试断点正常。
  3. 从0x7c00开始跟踪代码运行,将单步跟踪反汇编得到的代码与bootasm.S和bootblock.asm进行比较。
  4. 自己找一个bootloader或内核中的代码位置,设置断点并进行测试。
结合gdb和qemu源码级调试ucore

如题意我们要使用qemu并调试lab1中的软件,qemu的启动命令是:

qemu-system-i386 -hda bin/ucore.img -parallel stdio  # 让ucore在qemu模拟的x86硬件环境中执行。

qemu-system-i386 -S -s -hda bin/ucore.img -monitor stdio	# 用于与gdb配合进行源码调试。

该练习中使用第二个启动命令,其中的参数意思是:

-S :在启动时不启动CPU,需要在monitor中输入’c’,才能让qemu继续模拟工作。

-s :等待gdb连接到端口 1234

-had file :使用file作为硬盘的镜像。

-monitor dev :重定向monitor 到主机设备中。

其他可能要用到的参数如下:

-d :输出日志到 qemu.log 文件。

-serial dev :重定向虚拟串口到主机设备dev中。

-parallel dev :重定向虚拟并口到主机设备dev中

启动qemu后,qemu中的CPU并不会马上执行,这时我们启动gdb(再开一个终端,在里面启动gdb),在gdb命令行界面下,使用下面的命令连接到qemu:

target remote : 1234

另外为了让gdb获知调试那个文件和文件中的符号信息,gdb中使用file命令:

file ./bin/kernel

这样gdb就会载入这个文件中的符号信息了。

这样调试是不是很方便,但是如果你需要多次使用gdb的话,你需要多次进行远程连接,输入较多的东西,很麻烦。为了方便,可以将这些命令存在脚本中,并让gdb在启动的时候自动载入。

举例:我们将命令放在文件tools/gdbinit中,运行的时候只需要使用下面的命令启动gdb即可:

gdb -x tools/gdbinit

gdb -tui -x tools/gdbinit   # 以更好看的界面执行

在调试的时候,我们也许需要调试的不是i386保护模式的代码,比如8086实模式的代码,我们需要设定当前使用的架构:

(gdb) set arch i8086

说了这么多,我们开始写练习。

练习2.1

CPU加电后执行的第一条指令的位置是文件bin/kernel开始的位置,所以首先我们要调试该文件。

file bin/kernel

接下来我们设置断点,bin/kernel文件第一条指令是kern_init函数。

break kern_init
continue

这些东西其实都在tools/gdbinit里面原本就有,所以我们只要将qemu和gdb连接即可。

1 修改lab1/tools/gdbinit,文件后面添加内容为:

set architecture i8086	# 设置当前调试的CPU是8086
target remote : 1234	# 远程连接qemu

2 在lab1目录下,执行

make debug

3 在看到gdb的调试界面(gdb)后,在gdb调试界面下执行如下命令

si		# 单步追踪BIOS

4 在gdb界面下,可通过如下命令来看BIOS的代码

x /2i $pc		# 显示当前eip处的汇编指令
练习2.2

1 修改lab1/tools/gdbinit的内容,在文件末尾加上

set architecture i8086
target remote : 1234
b *0x7c00				# 在0x7c00处设置断点
c
x /2i $pc				# 显示当前eip处的汇编指令
set architecture i386  	# 设置当前调试得CPU是80386

2 执行后在lab1目录下,执行

make debug
练习2.3

将2.2的gdbinit 中的 x/2i $pc 改成 x/10i $pc,多找几条指令和bootasm.S ,bootblock.asm 比较即可发现,三者指令完全相同。

练习2.4

参照上述即可,将file 的文件改成bootloader中的文件即可。

练习3:分析BootLoader进入保护模式的过程。

练习3.1 A20的打开

1 首先关中断
在这里插入图片描述

2 同时等待数据缓冲区中没有数据以后
在这里插入图片描述

3 准备操作
发送(P2) 命令到8042 inputbuffer在这里插入图片描述

4 等待 8042 Input buffer 为空,将P2得到字节的第2位置置一,然后写入8042Input buffer。
在这里插入图片描述
到现在A20就打开了。

练习3.2 如何初始化GDT表

使用lgdt指令 寻找gdt表的初始位置。在这里插入图片描述

练习3.3 如何使能和进入保护模式

使能: 开启A20门

进入保护模式 :
在这里插入图片描述

cr0为控制寄存器,cr0中含有控制处理器操作模式和状态的系统控制标志。其中第零位标志是PE(Protection Enabled)

之后将编码方式转换为 .code32, 即可。

练习4:分析bootloader加载ELF格式的os的过程。

inline关键字 内联函数,编译器编译时将此函数实现插入,而不是像普通函数那样生成调用代码。

bootmain.c

练习4.1 bootloader如何读取硬盘扇区的?

读取文件,再判断是不是ELF格式,不是则死循环,否则读取文件中的程序。
bootmain中将指定地址**(0x10000)**的数据先转换成ELF文件中的elfhdr结构。如果不是ELF格式,就陷入死循环。否则从中获取待读取扇区的信息,之后进行读取。

elfhdr结构如下:
在这里插入图片描述
proghdr的结构如下:在这里插入图片描述
读取硬盘扇区的代码如下。
在这里插入图片描述

练习4.2 bootloader是如何加载ELF格式的os?

bootmain中将elfhdr结构中预设的程序入口地址,强制转换成无返回值,无参数的函数。并且调用这个函数,加载OS。

(void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))();

练习5 :实现函数调用堆栈跟踪函数

实现kdebug.c 中的函数print_stackframe。

通过阅读小结“函数堆栈”后,了解到编译器通过bp和sp的值来建立函数调用关系,bp的值总是上一层函数的bp在堆栈中的位置。了解了这个后,我们阅读kdebug.c的代码,kdebug.c提供了三个很有用的函数。

  • read_ebp() :获取当前ebp的值。
  • read_eip() : 获取当前eip的值。
  • print_debuginfo(eip - 1) : 打印当前调用函数的信息。

根据kdebug.c中的提示和给的函数,我们写出函数代码如下:
在这里插入图片描述

练习6 完善中断初始化和处理

练习6.1

中断描述符表,一个表项栈8个字节,其中2-3字节是段选择子,0-1字节和6-7字节拼成位移,两者联合便是中断处理程序的入口地址。

练习6.2在这里插入图片描述
练习6.3在这里插入图片描述
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值