【BIOS中断】磁盘与 INT 13H

INT 13h 是 x86 PC 架构中 BIOS 提供的磁盘服务中断,用于在实模式下对软盘、硬盘等存储设备进行底层读写操作。它是操作系统引导程序(如 MBR、bootloader)访问磁盘的唯一标准接口

一、基本概念

(一)int 13H

  • 中断号0x13(十进制 19)
  • 调用方式int 0x13
  • 运行环境实模式(Real Mode)
  • 支持设备:软盘(Floppy)、硬盘(HDD)、早期 USB 存储(需 BIOS 支持)
  • 寻址方式
    • 传统 CHS(柱面-磁头-扇区):最大 ~8.4 GB
    • 扩展 LBA(逻辑块地址):通过 INT 13h Extensions(AH=42h)支持大容量磁盘

💡 BIOS 将 INT 13h 的中断向量(地址)存放在内存 0x0000:0x004C 处。

(二)磁盘结构

(三)磁盘布局

磁盘的布局(Disk Layout)是指存储设备(如硬盘、SSD、软盘)上数据的物理或逻辑组织方式。不同层级(硬件、BIOS、操作系统)对磁盘布局的理解不同。以下是 x86 PC 启动过程中的关键结构

1. 物理/传统布局(CHS 模型)

早期硬盘使用 CHS(Cylinder-Head-Sector) 模型:

  • 柱面(Cylinder):所有盘片上相同半径的磁道集合
  • 磁头(Head):每个盘面对应一个读写磁头
  • 扇区(Sector):每个磁道被划分为多个扇区(通常 512 字节/扇区

⚠️ 现代磁盘已不使用 CHS,但 BIOS 和 MBR 仍模拟此模型以保持兼容。

2. 逻辑布局(LBA 模型)

现代磁盘使用 LBA(Logical Block Addressing)

  • 扇区编号从 0 开始连续编号
  • LBA 0 = 第一个扇区
  • LBA 1 = 第二个扇区
  • ...
  • 总容量 = (LBA 最大值 + 1) × 512 字节

✅ LBA 是操作系统和现代 BIOS 使用的标准

二、PC 磁盘关键布局(启动相关)

(一)主引导记录(MBR)— LBA 0

偏移大小内容
0x000446 字节引导代码(Bootstrap Code)
0x1BE64 字节分区表(4 项 × 16 字节)
0x1FE2 字节签名(0x55AA)

💡 MBR 总共 512 字节,是磁盘的第一个扇区。

分区表项结构(16 字节):
偏移长度含义
01状态(0x80 = 可启动)
13起始 CHS(已废弃)
41分区类型(如 0x0B = FAT32, 0x83 = Linux)
53结束 CHS(已废弃)
84起始 LBA(关键!)
124分区总扇区数

✅ 现代系统只使用“起始 LBA”字段,忽略 CHS。


(二)分区布局(以主分区为例)

假设一个硬盘有 1 个主分区:

LBA 地址内容
0MBR
1 ~ N-1空闲(或第二阶段 bootloader)
N分区引导记录(PBR) / Volume Boot Record(VBR)
N+1 ~ ...文件系统数据(如 FAT 表、根目录、簇数据)

💡 N = 分区起始 LBA(来自 MBR 分区表)


(三)典型文件系统布局(以 FAT32 为例)

在分区内部(从 PBR 开始):

偏移(相对分区起始)内容
0x000PBR(512 字节)
• BPB(BIOS Parameter Block)
• 引导代码
• 签名(0x55AA)
0x00DBPB:每扇区字节数(通常 512)
0x00EBPB:每簇扇区数
0x01CBPB:FAT 表数量
0x024BPB:根目录起始簇
0x02CBPB:总扇区数(32 位)
0x036BPB:每个 FAT 表占用扇区数
紧随 PBRFAT 表 1
+ FAT 大小FAT 表 2(备份)
+ FAT 大小根目录区
之后数据区(文件内容)

(四)Linux ext2/ext3/ext4 布局

偏移内容
0x000超级块(Superblock)
• 文件系统元信息(块大小、inode 数等)
0x400块组描述符表(GDT)
后续块位图、inode 位图、inode 表、数据块

💡 ext 系列使用 块(Block) 而非扇区(通常 1K~4K/块)。


(五)启动过程中的磁盘访问流程

  1. BIOS 将 MBR(LBA 0) 加载到内存 0x7C00
  2. MBR 代码
    • 扫描分区表,找到活动分区(状态=0x80)
    • 用 INT 13h 读取该分区的 PBR(LBA = 分区起始 LBA) 到 0x7E00
  3. PBR 代码
    • 解析 BPB,定位 FAT 表/根目录
    • 读取 第二阶段 bootloader(如 GRUB 的 core.img 或 DOS 的 IO.SYS
  4. 第二阶段
    • 加载内核(如 vmlinuzKERNEL.SYS

三、通用寄存器约定

寄存器用途
AH功能号(子功能选择)
CF返回状态CF=0 成功,CF=1 失败
AL / AX输入/输出参数(依功能而定)
DL驱动器号(关键!)

AH功能编码

00H —磁盘系统复位 
01H —读取磁盘系统状态 
02H —读扇区 
03H —写扇区 
04H —检验扇区 
05H —格式化磁道 
06H —格式化坏磁道 
07H —格式化驱动器 
08H —读取驱动器参数 
09H —初始化硬盘参数 
0AH —读长扇区 
0BH —写长扇区 
0CH —查寻 

0DH —硬盘系统复位

0EH —读扇区缓冲区 
0FH —写扇区缓冲区 
10H —读取驱动器状态 
11H —校准驱动器 
12H —控制器RAM诊断 
13H —控制器驱动诊断 
14H —控制器内部诊断 
15H —读取磁盘类型 
16H —读取磁盘变化状态 
17H —设置磁盘类型 
18H —设置格式化媒体类型 
19H —磁头保护 
1AH —格式化ESDI驱动器  

驱动器号(DL)编码

设备
0x00软驱 A:
0x01软驱 B:
0x80第一块硬盘(主盘)
0x81第二块硬盘
0xE00xFF可能用于 CD-ROM(需 El Torito)

⚠️ 重要:当 BIOS 加载 MBR 时,会将启动驱动器号放入 DL,你的代码应直接使用它!

四、基础功能

(一)复位磁盘系统(AH = 00h)

mov ah, 0x00
mov dl, 0x80    ; 硬盘0
int 0x13
; CF=0: 成功;CF=1: 失败(AH=错误码)
  • 重置控制器,清除错误状态
  • 建议在读写前调用(提高兼容性)

(二)读取扇区(AH = 02h)✅ 最常用!

mov ah, 0x02    ; 读扇区
mov al, 1       ; 读 1 个扇区
mov ch, 0       ; 柱面低8位
mov cl, 2       ; 扇区号(1-63),位7-6为柱面高2位
mov dh, 0       ; 磁头号
mov dl, 0x80    ; 驱动器(硬盘0)
mov bx, 0x7E00  ; ES:BX = 目标缓冲区
int 0x13
jc error        ; CF=1 表示错误

🔢CHS 地址说明:

  • 扇区号从 1 开始(不是 0!)
  • CL 的位结构:text 
CL = [C9 C8 | S5 S4 S3 S2 S1 S0]
      柱面高2位     扇区号(1-63)

🔄 LBA → CHS 转换(假设 255 磁头/63 扇区):

sector = (LBA % 63) + 1;
head   = (LBA / 63) % 255;
cyl    = (LBA / 63) / 255;
// CL = (cyl >> 2) | sector;
// CH = cyl & 0xFF;

(三)写入扇区(AH = 03h)

mov ah, 0x03    ; 写扇区
mov al, 1       ; 写 1 个扇区
; ... 其他参数同读 ...
mov bx, buffer  ; ES:BX = 源数据
int 0x13

⚠️ 注意:很多 BIOS 禁止在 MBR 中写硬盘(安全限制)!

(四)获取驱动器参数(AH = 08h)

mov ah, 0x08
mov dl, 0x80    ; 查询硬盘0
int 0x13
; 返回:
; AL = 最后一个有效磁头号(0-based)
; CH = 最大柱面低8位
; CL = [C9 C8 | max_sector]
; DH = 最大磁头号(同 AL)
; DL = 驱动器数量(bit7=1表示硬盘)
  • 用于动态探测磁盘几何结构

(五)检测驱动器就绪(AH = 15h)

mov ah, 0x15
mov dl, 0x80
int 0x13
; 返回:
; AH = 状态
;   00h: 不支持
;   01h: 无介质
;   02h: 可移动盘,有介质
;   03h: 固定盘(硬盘)
; CX:DX = 扇区总数(仅当 AH=03h 时有效)
  • 可用于判断是否为硬盘

五、扩展功能

传统 CHS 无法访问 >8.4GB 磁盘。扩展 INT 13h(由 Enhanced Disk Drive Specification 定义)使用 LBA 寻址

(一)读取扇区(AH = 42h)

1. 定义磁盘地址包(Disk Address Packet, DAP)

struct DAP {
    uint8_t  size;        // = 0x10 (16 字节)
    uint8_t  reserved;    // = 0
    uint16_t count;       // 要读取的扇区数
    uint16_t offset;      // 目标缓冲区偏移(ES:offset)
    uint16_t segment;     // 目标缓冲区段地址
    uint64_t lba;         // 起始 LBA(64 位)
};

2. 使用示例

; 定义 DAP(在数据段)
dap:
    db 0x10             ; size
    db 0                ; reserved
    dw 1                ; 读 1 个扇区
    dw 0x7E00           ; offset
    dw 0x0000           ; segment
    dq 1                ; LBA = 1

; 调用扩展读
mov ah, 0x42
mov dl, 0x80            ; 驱动器
mov si, dap             ; DS:SI -> DAP
int 0x13
jc error

(二) 检测扩展支持

mov ah, 0x41
mov bx, 0x55AA          ; magic
mov dl, 0x80
int 0x13
; 如果 CF=0 且 BX=0xAA55,则支持扩展

✅ 优势:支持 64 位 LBA,可访问超大磁盘(理论上 2^64 扇区)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万法若空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值