lab 1实验报告
练习1:理解通过make生成执行文件的过程。
1.操作系统镜像文件ucore.img是如何一步一步生成的?
生成 bin/kern 部分
生成 init.o
生成 readline.o
生成 stdio.o
生成 kdebug.o
生成 kmonitor.o
生成 panic.o
生成 clock.o
生成 console.o
生成 intr.o
生成 picirq.o
生成 trap.o
生成 trapentry.o
生成 vectors.o
生成 pmm.o
生成 printfmt.o
生成 string.o
用上面 .o 文件连接生成 bin/kern
生成bin/bootblock部分
生成 bootasm.o
生成 bootmain.o
用上面两个.o文件生成 bin/bootblock
生成 bin/sign
生成 sign.o
用上面.o生成 bin/sign
生成 ucore.img
2.一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?
主引导扇区大小为512字节,并且最后结尾为 0x55,0xAA
练习2:使用qemu执行并调试lab1中的软件
1. 从CPU加电后执行的第一条指令开始,单步跟踪BIOS的执行。
(1).首先启动一个终端,使用 qemu -S -s -hda bin/ucore.img -monitor stdio 的方式启动qemu,等待gdb连接
(2).在启动一个终端,启动gdb用远程连接的方式连接qemu
(3).在qemu终端输入 x /6i $pc 这条指令,观察qemu启动时候首先执行的指令
发现第一条指令是一个长跳转,在gdb终端输入 i r观察寄存器值
可以看到现在的CS:IP --> 0xffff0,这是指向内存的开始位置,也是加电后bios初始化后cs:ip的位置。
然后在gdb终端输入si执行一条汇编指令,然后在qemu终端观察下面的执行指令已经变为下面
也就是第一条指令后跳转后的位置
2.在初始化位置0x7c00设置实地址断点,测试断点正常。
打开qemu和gdb,建立远程连接,在gdb终端输入 p *0x7c00,然后输入c执行
执行完毕,可以正常运行到断点
3.从0x7c00开始跟踪代码运行,将单步跟踪反汇编得到的代码与bootasm.S和 bootblock.asm进行比较。
使用si单步执行观察下面10条指令,进行比较。
反汇编得到的代码是:
代码指令比较简洁,没有多余东西,bootasm代码是:
代码也比较简洁,不过里面带有注释,bootlock.asm代码是:
发现里面除了具有注释,还有代码所在的位置,位置与反编译得到的一致
4.自己找一个bootloader或内核中的代码位置,设置断点并进行测试。
在gdb终端载入file ./bin/kernel,然后设置暂停点memset,用c执行,得到下面结果,在string里面暂停了下来
习题3.分析bootloader进入保护模式的过程
为何开启A20,以及如何开启A20
开启A20可以使用32根地址总线,如果不开启只能使用20根地址总线,寻址能力只有1MB,开启后寻址能力可以达到4GB。
打开A20方法,不断查看0x64端口的值,如果是2表示不忙,如果不忙,把x0d1写入0x64端口,把0xdf写入0x60端口
如何初始化GDT表
在bootasm.s里面有这样一段代码来对GDT进行了初始化
# Bootstrap GDT .p2align 2 # force 4 byte alignment gdt: SEG_NULLASM # null seg SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg for bootloader and kernel SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg for bootloader and kernel gdtdesc: .word 0x17 # sizeof(gdt) - 1 .long gdt # address gdt
如何使能和进入保护模式
movl %cr0, %eax orl $CR0_PE_ON, %eax movl %eax, %cr0 ljmp $PROT_MODE_CSEG, $protcseg
由上面代码可以看出进入保护模式是把cr0寄存器的最后一位编程1,然后跳转到保护模式段