lab1
启动流程
- BIOS(保存在ROM上) 从磁盘的boot sector上读取bootloader(在boot文件夹下) 程序代码到内存0x7c00到0x7dff上
-
bootloader程序有两个文件组成:boot/boot.S和boot/main.c . boot/boot.S是将processor由real mode 切换到 real mode(切换的流程可以阅读IA32-3A 9.9节switch mode),代码注意以下几点:
- enable A20 代码 (这段可以忽略,历史遗留原因)
- 使用以下代码定义了全局描述符表
- 设置CR0寄存器的PE位
- 在设置CR0后,需要立马进行一个call 命令或者jmp命令,在代码中是一个长跳转ljmp,这样做的原因是不能使用mov等指令显示修改的cs寄存器的内容, 只能使用call 或者jmp指令来隐式修改cs寄存器
-
上面两个图,第一个是GDTR的布局图,可以看出为什么gdtdesc这么设置的原因,第二个图可以看出段选择子为什么要设置为8(另外,其实jos不分段,所以GDT中两个段起始位置是0,结束位置是0xffffffff)
#全局描述符表 # Bootstrap GDT .p2align 2 # force 4 byte alignment gdt: SEG_NULL # null seg SEG(STA_X|STA_R, 0x0, 0xffffffff) # code seg SEG(STA_W, 0x0, 0xffffffff) # data seg gdtdesc: .word 0x17 # sizeof(gdt) - 1 .long gdt # address gdt
- boot/main.c 实现将kernel image 从disk读取到内存中,这里理解的难点在于不懂得elf文件的相关知识,这里推荐阅读<<程序员的自我修养>>.还有就是磁盘最小读取单位是sector,所以读取的内容可能比文件实际大小大一些.
- vma和lma区别:大部分这两着的值是一样的,但是kernel这两者是不一样的,在我看来(有待考证),VMA(link address)是elf文件中和其他elf文件链接的地址,可以看到kernel.asm中的汇编代码的地址用的是VMA,而LMA(load address)是实际加载到物理内存中的地址,这里的load address是在/kernel.ld中确定的.
- 在boot/main.c 中通过
((void (*)(void)) (ELFHDR->e_entry))();
来进入kernel,这是一个函数指针的调用,e_entry的值是在elf文件中确定的.此时就进入了kernel/entry.S文件.
6.这里有疑问 为什么要在进入kernel以后重新设置stack 这是因为之前的栈上一个单元是16bit的,现在是32bit,留着并没有什么意义.
ps. 后面的内容忘记保存了,不想在重写一遍 sad
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。