You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JOS Bootloader无MBR签名仍可加载的机制及MBR签名意义问询

关于JOS Bootloader无MBR签名仍可加载的技术解答

背景

我跟随麻省理工学院(MIT)的操作系统课程学习操作系统开发时发现:osdev wiki等多数教程中的Bootloader代码末尾都会使用Master Boot Record (MBR)签名(0xAA55),但JOS代码仓库中的Bootloader代码(boot/boot.S)并未使用该签名,却仍能被正常加载。以下是JOS Bootloader的核心代码片段:

#include <inc/mmu.h>

# Start the CPU: switch to 32-bit protected mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk into
# memory at physical address 0x7c00 and starts executing in real mode
# with %cs=0 %ip=7c00.

.set PROT_MODE_CSEG, 0x8     # kernel code segment selector
.set PROT_MODE_DSEG, 0x10    # kernel data segment selector
.set CR0_PE_ON,   0x1     # protected mode enable flag

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

 # 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

 # 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

 # 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

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

 .code32           # Assemble for 32-bit mode
protcseg:
 # Set up the protected-mode data segment registers
 movw  $PROT_MODE_DSEG, %ax  # Our data segment selector
 movw  %ax, %ds        # -> DS: Data Segment
 movw  %ax, %es        # -> ES: Extra Segment
 movw  %ax, %fs        # -> FS
 movw  %ax, %gs        # -> GS
 movw  %ax, %ss        # -> SS: Stack Segment

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

 # If bootmain returns (it shouldn't), loop.
spin:
 jmp spin

# 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

针对上述现象,以下是两个核心问题的解答:

1. BIOS如何识别并加载未带有MBR签名的Bootloader代码?

BIOS的启动校验逻辑并非在所有场景下都严格执行MBR签名检查:

  • 虚拟机环境的宽松处理:JOS实验常用的QEMU、Bochs等虚拟机BIOS,为了方便开发调试,默认跳过了MBR签名的校验步骤——只要磁盘第一个扇区(LBA 0)有512字节的数据,就直接加载到物理地址0x7c00并移交控制权。
  • 现代物理BIOS的兼容模式:很多物理机BIOS在处理本地硬盘启动时,也会放宽校验:即使没有0xAA55签名,只要第一个扇区的代码是可执行的,就会尝试运行。只有在处理可移动介质(如U盘、光盘)时,才会严格校验签名。
  • 二进制文件的填充特性:JOS的boot.S编译链接后,生成的二进制文件刚好填满512字节(未使用的字节会被链接器填充为0或随机值),BIOS加载时直接读取完整的512字节,并不会因为末尾没有签名就拒绝执行。

2. 在BIOS启动的场景下,MBR签名的核心意义是什么?

MBR签名(0xAA55)是PC启动规范中定义的合法性校验标记,核心作用有两个:

  • 区分有效引导程序与无效数据:早期PC磁盘的第一个扇区(MBR)包含引导代码(前446字节)和分区表(后64字节),最后两个字节的签名是BIOS判断该扇区是否为合法引导程序的依据。如果没有该签名,BIOS会认为这是无效的磁盘数据,转而尝试其他启动介质,或抛出“Missing operating system”类错误。
  • 避免异常执行:防止BIOS误加载空磁盘、损坏的分区表或其他非引导数据到内存执行,避免系统出现崩溃、死机等异常情况。

内容的提问来源于stack exchange,提问作者user15980977

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 10:36:05