软件建立
在这次实验中,我们会将xv6操作系统运行在模拟器qemu中。
qemu可以从github上获取,或者使用mit修改过的qemu源(工具链)
git clone https://github.com/geofft/qemu.git -b 6.828-1.7.0
进行./configure (只要i386和x86_64平台即可)
./configure --disable-kvm --target-list="i386-softmmu x86_64-softmmu"
然后编译安装
make && make install
获取xv6源代码(github上托管的是完善版本,不是实验版本)
git clone https://pdos.csail.mit.edu/6.828/2014/jos.git lab
然后编译,使用qemu模拟运行
make && make qemu
Exercise 1:
练习1并没有什么实质性内容,就是MIT建议我们要对汇编语言有个大致的了解,这样才能让后面的学习更加方便一点。
PC的物理地址空间
第1代PC基于16位的Intel8088处理器,只能寻址1Mb的物理内存。因此,早先PC的物理地址空间开始于0x00000000结束于0x0000FFFF而不是0xFFFFFFFF。标示为”Low Memory”的640kb空间只能用于随机访问(RAM)。
从0x000A0000开始到0x000FFFFF的384Kb空间被保留用于硬件寻址比如VGA。1MB保留空间中最重要的部分是BIOS,占据了从0x000F0000到0x000FFFFF的64Kb空间。BIOS主要是进行硬件检查和初始化操作,最后从硬盘或CD-ROM上装载操作系统,并将控制权移交。
Exercise 2:
使用GDB的’si’命令,去追踪ROM BIOS几条指令,并且试图去猜测,它是在做什么。但是不需要把每个细节都弄清楚。
主要是bios启动时进行硬件检查等一系列操作
在运行gdb的窗口中会将显示出PC机启动后运行BIOS的第一条命令,如下:
0xffff0: ljmp $0xf000, $0xe05b
这是运行的第一条指令,是一条跳转指令,跳转到0xfe05b地址处。至于要知道这个地址是怎么通过指令中的值计算出来的,我们需要先知道,当PC机启动时,CPU运行在实模式(real mode)下,而当进入操作系统内核后,将会运行在保护模式下(protected mode)。实模式是早期CPU,比如8088处理器的工作模式,这类处理器由于只有20根地址线,所以它们只能访问1MB的内存空间。但是CPU也在不断的发展,之后的80286/80386已经具备32位地址总线,能够访问4GB内存空间,为了能够很好的管理这么大的内存空间,保护模式被研发出来。所以现代处理器都是工作在保护模式下的。但是为了实现向后兼容性,即原来运行在8088处理器上的软件仍旧能在现代处理器上运行,所以现代的CPU都是在启动时运行于实模式,启动完成后运行于保护模式。BIOS就是PC刚启动时运行的软件,所以它必然工作在实模式。
至于这两个模式下的运行原理,可以看这个链接:http://blog.csdn.net/zdwzzu2006/article/details/4030948
这里先简单介绍一下地址的计算方法,在实模式下,指令中出现的地址都是采用
(段基址:段内偏移)
的形式的。其中这两个字段的值,通常是存放寄存器中的。其中段基址必须放在段寄存器中,包括CS(代码段), DS(数据段), SS(堆栈段), ES(扩展段)。不同的段寄存器存放的是你程序不同的段的起始地址。
但是由于8088CPU中寄存器都是16位,而CPU地址总线是20位的,我们怎么通过16位的寄存器去拼接20位的地址呢?
所以我们需要采用下面的方法:把段寄存器中的值左移4位,形成20位段基址,然后和16位段内偏移相加,就得到了真实地址。比如上面的指令中段寄存器的内容为0xf000,所以真实地址为 0xf0000<<4+0xe05b = 0xfe05b。