mit 6.828 lab 代码和笔记,以及中文注释源代码已放置在github中: https://github.com/yunwei37/xv6-labs
setup
实验内容采用git分发:
git clone https://pdos.csail.mit.edu/6.828/2018/jos.git lab测试的话可以使用:
make grade需要了解x86汇编以及内联汇编的写法,参看:
http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html https://pdos.csail.mit.edu/6.828/2018/readings/pcasm-book.pdf
运行 qemu
cd lab make make qemuPC的物理地址空间:
+------------------+ <- 0xFFFFFFFF (4GB) | 32-bit | | memory mapped | | devices | | | /\/\/\/\/\/\/\/\/\/\ /\/\/\/\/\/\/\/\/\/\ | | | Unused | | | +------------------+ <- depends on amount of RAM | | | | | Extended Memory | | | | | +------------------+ <- 0x00100000 (1MB) | BIOS ROM | +------------------+ <- 0x000F0000 (960KB) | 16-bit devices, | | expansion ROMs | +------------------+ <- 0x000C0000 (768KB) | VGA Display | +------------------+ <- 0x000A0000 (640KB) | | | Low Memory | | | +------------------+ <- 0x00000000使用 gdb 调试qemu:
打开新的窗口:
cd lab make qemu-gdb在另外一个终端:
make make gdb开始使用gdb调试,首先进入实模式;
IBM PC从物理地址0x000ffff0开始执行,该地址位于为ROM BIOS保留的64KB区域的最顶部。PC从CS = 0xf000和IP = 0xfff0开始执行。要执行的第一条指令是jmp指令,它跳转到分段地址 CS = 0xf000和IP = 0xe05b。物理地址 = 16 *网段 + 偏移量
然后,BIOS所做的第一件事就是jmp倒退到BIOS中的较早位置;
PC的软盘和硬盘分为512个字节的区域,称为扇区。
当BIOS找到可引导的软盘或硬盘时,它将512字节的引导扇区加载到物理地址0x7c00至0x7dff的内存中,然后使用jmp指令将CS:IP设置为0000:7c00,将控制权传递给引导程序装载机。
boot/boot.S
#include <inc/mmu.h> # 启动CPU:切换到32位保护模式,跳至C代码; # BIOS将该代码从硬盘的第一个扇区加载到 # 物理地址为0x7c00的内存,并开始以实模式执行 # %cs=0 %ip=7c00. .set PROT_MODE_CSEG, 0x8 # 内核代码段选择器 .set PROT_MODE_DSEG, 0x10 # 内核数据段选择器 .set CR0_PE_ON, 0x1 # 保护模式启用标志 .globl start start: .code16 # 汇编为16位模式 cli # 禁用中断 cld # 字符串操作增量,将标志寄存器Flag的方向标志位DF清零。 # 在字串操作中使变址寄存器SI或DI的地址指针自动增加,字串处理由前往后。 # 设置重要的数据段寄存器(DS,ES,SS) xorw %ax,%ax # 第零段 movw %ax,%ds # ->数据段 movw %ax,%es # ->额外段 movw %ax,%ss # ->堆栈段 # 启用A20: # 为了与最早的PC向后兼容,物理 # 地址线20绑在低电平,因此地址高于 # 1MB会被默认返回从零开始。 这边代码撤消了此操作。 seta20.1: inb $0x64,%al # 等待其不忙状态 testb $0x2,%al jnz seta20.1 movb $0xd1,%al # 0xd1 -> 端口 0x64 outb %al,$0x64 seta20.2: inb $0x64,%al # 等待其不忙状态 testb $0x2,%al jnz seta20.2 movb $0xdf,%al # 0xdf -> 端口 0x60 outb %al,$0x60 # 使用引导GDT从实模式切换到保护模式 # 并使用段转换以保证虚拟地址和它们的物理地址相同 # 因此 # 有效内存映射在切换期间不会更改。 lgdt gdtdesc movl %cr0,