《ORANGE'S:一个操作系统的实现》之 boot(MBR)

  • 引言
    阅读于渊的《ORANGE'S:一个操作系统的实现》,对一些知识点做一个笔记,方便以后复习相关知识。这一篇主要对boot代码进行讲解。

  • boot.asm
    计算机在POST加电自检时寻找启动盘,所谓启动盘只是一个以0xAA55 结束的,并且包含一段少于512B的执行码的扇区。BOIS发现引导扇区,就会将这512B的内容装载到内存地址0000:7c00处,然后跳转到0000:7c00处将控制权彻底交给这段代码。此后计算机不在由BOIS中固有的程序控制,而是由操作系统的一部分控制。第一句org 07c00h告诉编译器这段代码将会被加载到内存偏移地址为0x7c00处。所以启动扇区占用0x7C00 - 0x7FFF这512字节

org    07c00h            ; 告诉编译器程序加载到7c00处    
mov    ax, cs    
mov    ds, ax    
mov    es, ax    
call    DispStr            ; 调用显示字符串例程    
jmp    $            ; 无限循环
DispStr:    mov    ax, BootMessage    
mov    bp, ax            ; ES:BP = 串地址    
mov    cx, 16            ; CX = 串长度    
mov    ax, 01301h        ;
 AH = 13,  AL = 01h    
mov    bx, 000ch        ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)    
mov    dl, 0    int    10h            ; 10h 号中断  
  retBootMessage:        db    "Hello, OS world!"
times     510-($-$$)    db    0    ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw     0xaa55                ; 结束标志

那么为什么是加载到7c00处而不是其他地方呢?

0x7C00的定义
对于这个地址,它不属于Intel x86平台规范的,而是属于BIOS规范中定义的内容。0x7C00第一次出现在IBM PC 5150的BIOS处理int 19(19号中断)的时候,IBM PC 5150是x86(32位)IBM PC/AT系列的祖先,这款PC于1981年发布,使用了intel 8088(16位)的处理器和16KB的RAM内存,BIOS和微软的基本指令均放在该内存中。当打开电源,BIOS开始自检,然后出发19号中断,在处理19号中断时,BIOS检测电脑是否具有软盘、硬盘或是固定磁盘,如果有任何可以使用的磁盘,BIOS就将磁盘的第一个扇区(512B)加载到内存的0x7C00地址处。

0x7C00的前身
0x7C00地址第一次出现在IBM PC 5150的ROM bios中,在此之前使用的地址是0x200。使用该地址的原因主要有:当时8086中断向量使用地址为0x0-0x3FF;86-DOS从0x400处被加载;而它不使用0x200-0x3FF这段中断向量地址。因此这段0x200-0x3FF地址不能被其他程序使用,Tim Paterson(86-DOS开发者)选择0x200作为MBR加载地址。

0x7C00的意义
他们想留下32kb内更多的空间给操作系统来加载自己;8086/8088使用0x0-0x3FF作为中断向量,然后BIOS数据紧随之后;引导扇区是512字节,但是用于引导程序的栈或数据区域需要多于512字节;因此0x7C00,32kb中的最后1kb被选中。一旦操作系统被引导并开始,引导扇区将一直不会被使用指导重启,因此操作系统和应用程序可以自由的使用32KB的最后1kb空间。在操作系统被加载后,内存布局如下:

+——————— 0x0| Interrupts vectors(中断向量表)
+——————— 0x400| BIOS data area(BIOS的数据区域)
+——————— 0x5??| OS load area(操作系统加载区域)
+——————— 0x7C00| Boot sector(引导区域)
+——————— 0x7E00| Boot data/stack(引导数据/堆栈)
+——————— 0x7FFF| (not used)+——————— (…)**

以下是网上找的系统启动过程:

  1. 开机;
  2. BIOS 加电或按reset键后都要进行系统复位,复位后指令地址为 0ffff:fff0,这个地方只有一条JMP指令, 跳转到系统自检 ( Power On Self Test -- POST )程序处;
  3. 系统自检完成后,将硬盘的第一个扇区 (0头0道1扇区, 也就是Boot Sector)读入内存地址 0000:7c00 处;
  4. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于则转去尝试其他启动介质, 如果没有其他启动介质 则显示 "No ROM BASIC" 然后死机;
  5. 跳转到 0000:7c00 处执行 MBR 中的程序;
  6. MBR(manage boot recorder)程序 首先将自己复制到 0000:0600 处, 然后继续执行;
  7. 在主分区表中搜索标志为活动的分区,如果没有发现活动分区或有不止一个活动分区, 则转停止;
  8. 将活动分区的第一个扇区读入内存地址 0000:7c00 处;
  9. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于则 显示 "Missing Operating System" 然后停止, 或尝 试软盘启动或;
  10. 跳转到 0000:7c00 处继续执行特定系统的启动程序;
  11. 启动系统...  以上步骤中 2,3,4,5 步是由 BIOS 的引导程序完成. 6,7,8,9,10步由MBR中的引导程序完成.

Boot Sector 结构简介
1、Boot Sector组成

Boot Sector 也就是硬盘的第一个扇区, 它由 MBR (Master Boot Record),DPT (Disk Partition Table) 和 Boot Record ID(Magic Number) 三部分组成。

MBR 又称作主引导记录,占用 Boot Sector 的前 446 个字节 ( 0 to 0x1BD ),包含了硬盘的一系列参数和一段系统主引导程序。引导程序主要是用来在系统硬件自检完后负责从活动分区中装载并运行系统引导程序(引导操作系统)。它的最后一条执行语句是一条JMP指令,跳到操作系统的引导程序去。这里往往是引导型病毒的注入点,也是各种多系统引导程序的注入点。但是由于引导程序本身完成的功能比较简单,所以我们完全可以判断该引导程序的合法性(比如看JMP指令的合法性),因而也易于修复。象命令fdisk/mbr可以修复MBR和KV300这类软件可以查杀任意类型的引导型病毒,就是这个道理。

DPT 即主分区表,占用 64 个字节 (0x1BE to 0x1FD),记录了磁盘的基本分区信息。主分区表分为四个分区项, 每项 16 字节, 分别记录了每个主分区的信息(因此最多可以有四个主分区)。   Boot Record ID 即引导区标记,占用两个字节 (0x1FE and 0x1FF), 对于合法引导区, 它等于 0xAA55, 这是判别引导区是否合法的标志.

Boot Sector 的具体结构如下图所示:
0000 |------------------------------------------------|  
| |  
| |  
| Master Boot Record |  
| |  
| |  
| 主引导记录(446字节) |  
| |  
| |  
| |  
01BD | |  
01BE |------------------------------------------------|  
| |  
01CD | 分区信息 1(16字节) |  
01CE |------------------------------------------------|  
| |  
01DD | 分区信息 2(16字节) |  
01DE |------------------------------------------------|  
| |  
01ED | 分区信息 3(16字节) |  
01EE |------------------------------------------------|  
| |  
01FD | 分区信息 4(16字节) |  
|------------------------------------------------|  
| 01FE | 01FF |  
| 55 | AA |  |------------------------------------------------|

推荐阅读更多精彩内容