练习一 理解通过 make 生成执行文件的过程
问题
1:理解通过 make 生成执行文件的过程。(要求在报告中写出对下述问题的回答)
在此练习中,大家需要通过阅读代码来了解:
操作系统镜像文件 ucore.img 是如何一步一步生成的?(需要比较详细地解释 Makefile 中每一条相关命令和命令参数的含义,以及说明命令导致的结果)
一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?
实验前的环境准备:
因为实验要大量用到Gcc和qemu,所有我们要先安装这两个,主要是qemu的安装用到sudo apt-get install qemu-system
问题一
操作系统镜像文件 ucore.img 是如何一步一步生成的
我们在lab1的文件加下发现有makefile文件,在此目录下打开终端输入make “V=“得到以下输出
我们可以看到+后面的就是终端进行的操作,分别是:
cc kern/init/init.c //编译 init.c
cc kern/libs/stdio.c //编译 stdio.c
cc kern/libs/readline.c //编译 readline.c
cc kern/debug/panic.c//编译 panic.c
cc kern/debug/kdebug.c//编译 kdebug.c
cc kern/debug/kmonitor.c //编译 kmonitor
cc kern/driver/clock.c //编译 clock.c
cc kern/driver/console.c //编译 console.c
cc kern/driver/picirq.c //编译 picirq.c
cc kern/driver/intr.c//编译 intr.c
cc kern/trap/trap.c //编译 trap.c
cc kern/trap/vectors.S //编译 vector.S
cc kern/trap/trapentry.S //编译 trapentry.S
cc kern/mm/pmm.c//编译 pmm.c
cc libs/string.c //编译 string.c
cc libs/printfmt.c //编译 printgmt.c
ld bin/kernel//接下来用ld合并目标文件(object) 和 库文件(archive),生成kernel程序
cc boot/bootasm.S //编译 bootasm.S 作为bootblock的源文件
cc boot/bootmain.c //编译 bootmain.c,同上一个
cc tools/sign.c //编译 sign.c
ld bin/bootblock//这里是把boot下的两个源文件与目标文件连接(bootasm.o obj 和bootmain.o -o bootblock.o),最后生成bootblock程序
所有整个ucore.img的生成流程就是:首先先创建一个大小为10000字节的块儿
再编译连接生成kernel程序,然后编译连接生成bootblock程序,最后生成ucore.img的磁盘映像文件
问题二
一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?
分析tools中的sign.c文件我们知道,硬盘主引导扇区的大小是不大于512个字节的,同时最后的两位是0x55和0xAA
练习二 使用qemu执行并调试lab1中的软件
为了熟悉使用qemu和gdb进行的调试工作,我们进行如下的小练习:
- 从CPU加电后执行的第一条指令开始,单步跟踪BIOS的执行。
- 在初始化位置0x7c00设置实地址断点,测试断点正常。
- 从0x7c00开始跟踪代码运行,将单步跟踪反汇编得到的代码与bootasm.S和 bootblock.asm进行比较。
- 自己找一个bootloader或内核中的代码位置,设置断点并进行测试。
问题一
默认的gdb需要进行一些额外的配置才进行qemu的调试任务。qemu和gdb之间使用网络端口1234进行通讯。在打开qemu进行模拟之后,执行gdb并输入
target remote localhost:1234
即可连接qemu,此时qemu会进入停止状态,听从gdb的命令。
启动QEMU
qemu-system-i386 -S -s -hda bin/ucore.img -monitor stdio # 用于与gdb配合进行源码调试。
因为我们要启动的是i386系统,
-S 是指在启动时不启动CPU,需要在monitor中输入’c’,才能让qemu继续模拟工作。
-s :等待gdb连接到端口 1234
-hda file :使用file作为硬盘的镜像。
-monitor dev :重定向monitor 到主机设备中。
在出现QUEU的对话框后,重新打开一个新的终端,进入GDB中连接QEMU
再输入查看寄存器指令后:
我们可以看到CS和EIP的位置分别在0xfff0和0xf000,这就是加电后BIOS初始化后的CS:IP位置
问题二
在初始化位置0x7c00设置实地址断点,测试断点正常。
我们在初始化位置设置断点,gdb模式下执行c指令,可以看到在0x7c00处停下,然后通过x/20i $pc查看20条指令,然后我们查看此时寄存器的值,EIP的位置到了0x7c00输入,si可以继续单步调试
问题三
bootasm.S中可以看到与上面看到的20条指令是按相同顺序排下来的,一致性极高。
问题四
如果我们要看kern_init的位置,可以直接break kern_init,在此处设置断点,可以看到在此处停下。