4. BIOS 中断服务:BIOS 中断向量表 (IVT) 的建立与常用中断服务

当 BIOS 完成硬件自检 (POST) 后,下一个关键步骤是为操作系统和引导加载程序提供标准化的硬件访问接口。这一接口通过 BIOS 中断服务实现,其核心数据结构是 中断向量表 (IVT)。IVT 的建立标志着系统从实模式固件控制向软件可编程控制过渡的里程碑。

4.1 中断向量表 (IVT) 的建立

在 x86 实模式下,IVT 是一张位于内存地址 0x00000 至 0x003FF(共 1KB)的表格。每个表项占用 4 字节,包含一个中断处理程序的段地址(2 字节)和偏移地址(2 字节)。BIOS 在 POST 阶段负责填充这张表,将硬件中断、软件中断与对应的服务例程关联起来。

中断号 向量地址 用途 服务提供者
0x00 – 0x07 0x0000 – 0x001F CPU 异常处理(除零、单步、NMI 等) BIOS / CPU
0x08 – 0x0F 0x0020 – 0x003F 硬件中断(IRQ0 – IRQ7,如时钟、键盘) BIOS
0x10 – 0x1F 0x0040 – 0x007F BIOS 软件中断服务(视频、磁盘、串口等) BIOS
0x20 – 0xFF 0x0080 – 0x03FF 用户程序 / 操作系统使用(部分保留) 用户 / DOS
实模式地址计算: 中断向量地址 = 中断号 × 4。例如,int 0x10 的向量存储在 0x0000:0x0040 处,前 2 字节为偏移量,后 2 字节为段基址。

4.2 常用 BIOS 中断服务详解

在引导加载程序(如 GRUB Stage 1)和早期内核初始化阶段,最常调用的两个 BIOS 中断是 int 10h(视频服务)和 int 13h(磁盘服务)。它们提供了无需了解底层硬件细节即可操作屏幕和存储设备的能力。

4.2.1 int 10h – 视频显示服务

int 10h 是 BIOS 提供的核心视频输出接口,支持文本模式与图形模式。在引导阶段,系统默认处于 80×25 文本模式(模式 03h)。

  • 功能号 (AH): 通过 AH 寄存器指定子功能。
  • 常用子功能:
    • AH=0x0E:以电传方式 (Teletype) 在光标位置显示字符,AL 存放字符 ASCII 码,BL 存放前景色。
    • AH=0x00:设置显示模式,AL 存放模式号(如 03h 为文本模式,13h 为 320×200 256 色图形模式)。
    • AH=0x02:设置光标位置,DH=行,DL=列,BH=页号。
    • AH=0x09:在光标位置显示字符及属性,AL=字符,BL=属性,CX=重复次数。
引导阶段典型调用: 引导加载程序常使用 int 0x10, AH=0x0E 输出启动信息字符串,例如打印 "Loading kernel..."。
; 示例:使用 int 10h 在屏幕上打印字符 'A'
mov ah, 0x0E    ; 功能号:电传输出
mov al, 'A'     ; 要显示的字符
mov bh, 0x00    ; 页号 0
mov bl, 0x07    ; 前景色:白色(文本模式)
int 0x10        ; 调用 BIOS 视频中断

4.2.2 int 13h – 磁盘 I/O 服务

int 13h 是 BIOS 提供的底层磁盘读写接口,引导加载程序通过它从软盘、硬盘或 USB 设备读取内核映像到内存。该中断使用 CHS(柱面/磁头/扇区) 或 LBA(逻辑块地址) 两种寻址方式。

功能号 (AH) 功能描述 输入参数 输出参数
0x02 读取扇区 DL=驱动器号, DH=磁头, CH=柱面低8位, CL=扇区(高2位+低6位), AL=扇区数, ES:BX=缓冲区地址 CF=0 成功, AH=状态码, AL=实际读取扇区数
0x03 写入扇区 同上 CF=0 成功, AH=状态码
0x08 获取驱动器参数 DL=驱动器号 CF=0 成功, CH=最大柱面低8位, CL=每磁道扇区数, DH=最大磁头数, DL=驱动器数量
0x41 检测扩展 int 13h (LBA) 支持 DL=驱动器号, BX=0x55AA CF=0 支持, AH=扩展版本, BX=0xAA55
实模式限制: int 13h 一次最多读取 128 个扇区(64KB),且缓冲区地址 ES:BX 必须在 1MB 以下(实模式地址空间限制)。引导加载程序通常分多次读取大内核映像。
; 示例:使用 int 13h 从软盘 (DL=0x00) 读取 1 个扇区到内存 0x7C00
mov ah, 0x02        ; 功能号:读取扇区
mov al, 0x01        ; 读取 1 个扇区
mov ch, 0x00        ; 柱面 0
mov cl, 0x02        ; 扇区 2 (扇区编号从 1 开始)
mov dh, 0x00        ; 磁头 0
mov dl, 0x00        ; 驱动器 A:
mov bx, 0x7C00      ; 缓冲区偏移地址
mov es, bx          ; 段地址设为 0x0000
mov bx, 0x7C00      ; ES:BX = 0x0000:0x7C00
int 0x13            ; 调用 BIOS 磁盘中断
jc disk_error       ; 如果 CF=1,跳转到错误处理

4.3 IVT 与中断服务调用流程

下图展示了从应用程序调用 int 0x13 到 BIOS 执行磁盘读取的完整硬件与软件交互流程。

BIOS 中断调用流程:int 13h 示例 BIOS 中断调用流程:int 13h 磁盘读取 应用程序 / 引导程序 执行 int 0x13 IVT 查表 (0x4C) BIOS 磁盘服务例程 磁盘控制器 / 硬件 返回 (iret) 说明:CPU 收到 int 指令后,自动从 IVT 获取中断处理程序地址,保存标志寄存器与返回地址,然后跳转执行。

4.4 中断服务的关键寄存器约定

调用 BIOS 中断时,必须严格遵守寄存器传参约定。错误的寄存器值可能导致系统挂起或数据损坏。

  • AH: 功能号,决定中断内部执行哪个子服务。
  • AL / BX / CX / DX: 子功能参数,含义随功能号变化。
  • ES:BX: 用于数据传输的缓冲区指针(磁盘、内存操作)。
  • DS:SI / ES:DI: 字符串操作或数据结构指针。
  • CF (进位标志): 大多数 BIOS 调用使用 CF 表示错误(CF=1 表示失败),AH 中返回错误码。
实模式中断与保护模式中断的区别: 在实模式下,IVT 直接位于物理地址 0x00000;进入保护模式后,IVT 被中断描述符表 (IDT) 替代,BIOS 中断服务不再可用。因此,所有 BIOS 调用必须在进入保护模式 之前 完成。

4.5 常用中断号速查表

下表列出了引导阶段最常使用的 BIOS 中断号及其主要用途,帮助开发者在编写引导代码时快速定位。

中断号 名称 主要用途 引导阶段使用频率
int 0x10 视频服务 显示字符、设置模式、光标控制 高
int 0x13 磁盘服务 读取/写入扇区、获取驱动器参数 高
int 0x16 键盘服务 读取按键、检测按键状态 中
int 0x12 内存大小检测 返回连续内存大小 (KB) 中
int 0x15 系统服务 内存映射 (E820h)、系统配置 中
int 0x1A 时间服务 读取 RTC 时间、系统时钟 低

4.6 中断向量表的初始化流程

BIOS 在 POST 阶段按以下顺序初始化 IVT,确保每个中断向量指向有效的处理程序:

  1. 清空 IVT 区域: 将 0x00000 – 0x003FF 全部填充为 0x0000:0x0000,防止未初始化的向量被误调用。
  2. 填充 CPU 异常向量 (0x00 – 0x07): 指向 BIOS 提供的默认异常处理程序(通常只显示错误码并停机)。
  3. 填充硬件中断向量 (0x08 – 0x0F): 指向 8259A 可编程中断控制器 (PIC) 对应的 BIOS 默认处理程序。
  4. 填充软件中断向量 (0x10 – 0x1F): 指向 BIOS 各功能模块的服务例程(视频、磁盘、键盘等)。
  5. 填充用户可用向量 (0x20 – 0xFF): 初始化为指向一个简单的 iret 指令(空操作),供操作系统后续覆盖。
引导加载程序的责任: 在接管系统控制权后,引导加载程序通常会重新编程 8259A PIC 并设置自己的中断处理程序,但在此之前,所有 I/O 操作仍依赖 BIOS 中断服务。

通过 IVT 和 BIOS 中断服务,引导加载程序能够在无需了解具体硬件寄存器的情况下,完成屏幕输出、磁盘读取和内存检测等关键操作。这些中断服务构成了实模式下硬件抽象层的基础,也是 Linux 内核启动流程中从固件到软件过渡的桥梁。