MIT6.828 LAB1 PART2.1The Boot Loader

实验内容

        PC机的软盘和硬盘被划分为固定的512字节的扇区(sector)。扇区是磁盘的最小传输粒度:每个读或写操作的大小必须是一个或多个扇区。第一个扇区称为the boot sector引导扇区,从引导扇区加载操作系统。当BIOS找到可以启动的软盘或硬盘之后,这个512个字节的启动扇区就会被加载到内存,地址为0x7c00~0x7dff区域。

      bootloader程序的大小必须是小于512个字节的。bootloader由一个汇编文件boot/boot.S以及一个C语言文件boot/main.c组成。bootloader要完成以下主要功能:

1. bootloader要把处理器从实模式转换为保护模式,因为只要在保护模式下软件才可以访问超过1MB空间的内容。

2. boot loader可以通过使用x86的特定的IO指令,直接访问IDE磁盘设备寄存器,从磁盘中读取内核。(这个功能还没搞懂,标记一下)

Exercise 3

启动gdb调试。设置断点在0x7c00处,执行c,可以看到QEMU终端显示Boot from hard disk.

执行x/30i 0x7c00可以看到一段汇编语言。 这条gdb指令是把存放在0x7c00以及之后30字节的内存里面的指令反汇编出来。

(gdb) b *0x7c00
Breakpoint 1 at 0x7c00
(gdb) c
Continuing.
The target architecture is assumed to be i8086
[   0:7c00] => 0x7c00:	cli    

Breakpoint 1, 0x00007c00 in ?? ()
(gdb) x/30i 0x7c00
=> 0x7c00:	cli    
   0x7c01:	cld    
   0x7c02:	xor    %ax,%ax
   0x7c04:	mov    %ax,%ds
   0x7c06:	mov    %ax,%es
   0x7c08:	mov    %ax,%ss
   0x7c0a:	in     $0x64,%al
   0x7c0c:	test   $0x2,%al
   0x7c0e:	jne    0x7c0a
   0x7c10:	mov    $0xd1,%al
   0x7c12:	out    %al,$0x64
   0x7c14:	in     $0x64,%al
   0x7c16:	test   $0x2,%al
   0x7c18:	jne    0x7c14
   0x7c1a:	mov    $0xdf,%al
   0x7c1c:	out    %al,$0x60
   0x7c1e:	lgdtw  0x7c64
   0x7c23:	mov    %cr0,%eax
   0x7c26:	or     $0x1,%eax
   0x7c2a:	mov    %eax,%cr0
   0x7c2d:	ljmp   $0x8,$0x7c32
   0x7c32:	mov    $0xd88e0010,%eax
   0x7c38:	mov    %ax,%es
   0x7c3a:	mov    %ax,%fs
   0x7c3c:	mov    %ax,%gs
   0x7c3e:	mov    %ax,%ss

另外,同样在0x7c00处设置断点,使用vim打开boot/boot.S,并与反汇编指令进行比较。

.globl start
start:
  .code16                     # Assemble for 16-bit mode
  cli                         # Disable interrupts
  cld                         # String operations increment

可以看到,cli是bootloader执行的第一条指令。作用是关闭所有中断。

cld: clear direction flag, 指定之后发生的串处理操作的指针移动方向。(啥意思没搞懂 mark一下)

# Set up the important data segment registers (DS, ES, SS).
  xorw    %ax,%ax             # Segment number zero
  movw    %ax,%ds             # -> Data Segment
  movw    %ax,%es             # -> Extra Segment
  movw    %ax,%ss             # -> Stack Segment

以上四条指令是把三个段寄存器, Data Segment, Extra Segment, Stack Segment全部清零,为进入保护模式做准备。

 # Enable A20:
  #   For backwards compatibility with the earliest PCs, physical
  #   address line 20 is tied low, so that addresses higher than
  #   1MB wrap around to zero by default.  This code undoes this.
seta20.1:
  inb     $0x64,%al               # Wait for not busy
  testb   $0x2,%al
  jnz     seta20.1

  movb    $0xd1,%al               # 0xd1 -> port 0x64
  outb    %al,$0x64

seta20.2:
  inb     $0x64,%al               # Wait for not busy
  testb   $0x2,%al
  jnz     seta20.2

  movb    $0xdf,%al               # 0xdf -> port 0x60
  outb    %al,$0x60

以上指令的作用是准备把PC的工作模式从实模式转换为保护模式。使能A20线,代表可以进入保护模式了。

# Switch from real to protected mode, using a bootstrap GDT
  # and segment translation that makes virtual addresses 
  # identical to their physical addresses, so that the 
  # effective memory map does not change during the switch.
  lgdt    gdtdesc
  movl    %cr0, %eax
  orl     $CR0_PE_ON, %eax
  movl    %eax, %cr0

gdtdesc是一个标识符表示一个内存地址。从这个内存地址开始,之后的6个字节存放着GDT表的长度和起始地址。

接着的三条指令是修改CR0寄存器的内容。把CR0寄存器的bit0置1,CR0寄存器的bit0是保护模式启动位,把这位置0之后表示保护模式启动。

 # Jump to next instruction, but in 32-bit code segment.
  # Switches processor into 32-bit mode.
  ljmp    $PROT_MODE_CSEG, $protcseg

当前的运行模式切换成了32位地址模式。

 # Set up the stack pointer and call into C.
  movl    $start, %esp
  call bootmain

设置esp寄存器的值,准备跳转到main.c文件中bootmain函数。

接下来,关闭boot.S文件,用vim指令打开boot/main.c文件。并且追踪到bootmain()函数。

bootmain()函数中首先调用的是函数readseg,根据注释理解它的功能是:把距离内核地址offset个偏移量存储单元作为起始地址,把它和它之后的count字节的数据读出送入以pa为起始地址的内存地址。实际上这就是把内核的第一个页的内容的内容读取的内存地址ELFHDR(0x10000)处。其实就是把操作系统映像文件的elf头部读取放入内存中。

[注] elf是一种文件格式,主要被用来把程序存放到磁盘上。是在程序被编译和链接后被创建出来的。一个elf文件包括多个段。对于一个可执行程序,通常包含存放代码的文本段(text section),存放全局变量的data段,存放字符串常量的rodata段。elf文件的头部就是用来描述这个elf文件如何在存储器中存储。

// Read 'count' bytes at 'offset' from kernel into physical address 'pa'.
// Might copy more than asked
void
readseg(uint32_t pa, uint32_t count, uint32_t offset)

参考文章https://www.cnblogs.com/fatsheep9146/p/5115086.html

猜你喜欢

转载自blog.csdn.net/qq_43012789/article/details/107088736