lab1

启动流程

  1. BIOS(保存在ROM上) 从磁盘的boot sector上读取bootloader(在boot文件夹下) 程序代码到内存0x7c00到0x7dff上
  2. GDTR.pngSegment Selectorbootloader程序有两个文件组成:boot/boot.S和boot/main.c . boot/boot.S是将processor由real mode 切换到 real mode(切换的流程可以阅读IA32-3A 9.9节switch mode),代码注意以下几点:

    1. enable A20 代码 (这段可以忽略,历史遗留原因)
    2. 使用以下代码定义了全局描述符表
    3. 设置CR0寄存器的PE位
    4. 在设置CR0后,需要立马进行一个call 命令或者jmp命令,在代码中是一个长跳转ljmp,这样做的原因是不能使用mov等指令显示修改的cs寄存器的内容, 只能使用call 或者jmp指令来隐式修改cs寄存器
    5. 上面两个图,第一个是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
      
      
  3. boot/main.c 实现将kernel image 从disk读取到内存中,这里理解的难点在于不懂得elf文件的相关知识,这里推荐阅读<<程序员的自我修养>>.还有就是磁盘最小读取单位是sector,所以读取的内容可能比文件实际大小大一些.
  4. vma和lma区别:大部分这两着的值是一样的,但是kernel这两者是不一样的,在我看来(有待考证),VMA(link address)是elf文件中和其他elf文件链接的地址,可以看到kernel.asm中的汇编代码的地址用的是VMA,而LMA(load address)是实际加载到物理内存中的地址,这里的load address是在/kernel.ld中确定的.
  5. 在boot/main.c 中通过((void (*)(void)) (ELFHDR->e_entry))();来进入kernel,这是一个函数指针的调用,e_entry的值是在elf文件中确定的.此时就进入了kernel/entry.S文件.

6.这里有疑问 为什么要在进入kernel以后重新设置stack 这是因为之前的栈上一个单元是16bit的,现在是32bit,留着并没有什么意义.

ps. 后面的内容忘记保存了,不想在重写一遍 sad


查查
0 声望0 粉丝