CSCI 555 (MIT 6.828) Lab 1 记录
Contents
这学期选了cs555 Advanced Operating System, 据说这课load比较大, 但对于头铁又放飞gpa的我来说根本就无所畏惧(笑). 教授是个大佬,每节课带着读一篇system方向的经典paper,讲的挺好. 然后实验是搬运的mit 6.828, 网上资源很多,感觉工作量会比较大,这学期秃头预定😂
这系列我觉得我是不会弃坑的(真香警告)… 这里就记录一下码代码的大致心得以及我觉得重点的地方吧,抄答案还是另寻别处吧,以下正文
part 0: setup envoronment
把课程代码clone下来之后编译, 我用的MacOS, 版本10.13 high Sierra, 总结就是Homebrew大法好, brew装了i386-elf-gcc
, i386-elf-gdb
, i386-elf-binutils
三件套,再改改makefile就完事了,做完lab1现在没发现啥问题…
part 1: PC Bootstrap
PC的物理地址空间大致长这样:
|
|
有个问题:为什么16位的PC能寻址1MB(2^20)的地址空间呢?
早期16位PC是基于intel 8088处理器, 而8088/8086这些16位的处理器是靠分段(segmentation)来寻址20位地址空间的.计算公式是physical address = (16 * segment address + offset)
8088的BIOS设计放在0x000f0000-0x000fffff
处, 当处理器启动的时候,进入实模式,起始地址为0xffff0 (CS:IP = 0xf000:0xfff0)
BIOS运行时会建立中断描述符表(interrupt descriptor table)以及初始化一系列硬件设备,之后搜寻可启动的设备(CD-ROM之类的),找到之后BIOS从设备中读取引导程序(boot loader)然后将控制权转交给它.
part 2: The Boot Loader
PC硬盘被划分为许多512byte大小的扇区,一个可以启动的磁盘的第一个扇区就是引导程序,BIOS会将其读入0x7c00~0x7dff
的地址中,之后执行jmp
指令跳转到0x7c00处,将控制转交给引导程序.至于为什么是0x7c00,这是历史原因了,详情参见wiki
boot loader 主要做这么些事:
- 将处理器从实模式切换到32位保护模式
- 将整个kernel读入memory中
- 控制转交给kernel
这里是通过设置CR0寄存器来切换到保护模式的
kernel是ELF格式的,我们主要关注这几个部分:
- .text: 程序的可执行指令
- .rodata: read-only data
- .data: 程序初始化的数据 (像int x = 0之类的)
可以使用objdump来查看详细信息
其中.text部分的link address
和load address
需要注意:
- link address: 指令运行时的地址,一般是虚拟地址
- load address: 指令load进内存的地址
可以发现实模式下这两地址是一样的,因为并没有开启虚存,指令执行的时候就没有地址映射关系
看一下main.c里面,kernel的入口是((void (*)(void)) (ELFHDR->e_entry))();
在boot.asm中可以看到对应boot loader执行的最后一条指令是7d73: ff 15 18 00 01 00 call *0x10018
. 之后控制交给kernel,从entry.S开始运行,第一条指令是f010000c: 66 c7 05 72 04 00 00 movw $0x1234,0x472
.
part 3: The Kernel
这里JOS其实有两个地址映射的关系,在kern/entrypgdir.c里面可以看到:
- Map VA’s [0, 4MB) to PA’s [0, 4MB)
- Map VA’s [KERNBASE, KERNBASE+4MB) to PA’s [0, 4MB) 其中第一个映射只是为了entry.S中的指令能正确执行,过了entry.S就没用了,具体可以看代码和注释
format printing这个只要看一下kern/printf.c, lib/printfmt.c, kern/console.c
这三个地方就清楚了. 这里有个challenge是在控制台输出彩色文字,一个思路是用ANSI escape sequence,也就是类似\u001b[31mHelloWorld\u001b[0m
这样的输出. 还有一个思路是可以参考一下VGA text buffer的格式,修改前景色那几位就行了.
stack可以看一下kernel.asm里面test_backtrace对esp,ebp的操作.
stabs可以看一下这里然后看看生成的.s文件大概就能看出stabs里面都存了啥东西,就比较好理解kdebug.c了
Author xymeow
LastMod 2019-03-03