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

自制OS从USB启动的BIOS设置与INT 0x13调用问题求助

用NASM编写INT 0x13调用实现USB启动(LBA模式)

嘿,我之前折腾自制OS从USB启动时也踩过一模一样的坑——传统的CHS(柱面/磁头/扇区)模式只适配软盘和老式硬盘,USB设备得用**LBA(逻辑块寻址)**的扩展BIOS调用才行,给你一步步拆解实操方案:

核心思路:放弃CHS,切换到INT 0x13扩展功能

USB设备在BIOS里会被识别为类硬盘存储设备,驱动器号从0x80开始(软盘固定是0x00),不能再用INT 0x13的传统读扇区功能(0x02),必须用功能号0x42的扩展读扇区调用,这个调用依赖DAP(Disk Address Packet)结构传递参数。

第一步:先验证BIOS是否支持LBA扩展

调用0x42之前,得先确认BIOS支持这个扩展功能,用INT 0x13的功能0x41做检测:

; 检查INT 0x13扩展支持
mov ah, 0x41
mov bx, 0x55AA
mov dl, 0x80        ; USB设备驱动器号,通常是0x80(第一个硬盘/USB设备)
int 0x13
jc no_lba_support   ; CF置位=不支持扩展
cmp bx, 0xAA55
jne no_lba_support  ; 返回BX不是0xAA55=不支持扩展

第二步:定义DAP结构

DAP是LBA模式下传递读写参数的标准结构,必须提前在内存中定义,NASM写法如下:

dap:
    db 0x10           ; DAP固定大小(16字节)
    db 0x00           ; 保留位,必须为0
    dw 0x01           ; 要读取的扇区数(这里读1个,可按需修改)
    dw 0x7E00         ; 数据缓冲区的偏移地址(比如放在MBR之后的0x7E00)
    dw 0x0000         ; 数据缓冲区的段地址(实模式下0x0000:0x7E00 = 物理地址0x7E00)
    dq 0x01           ; LBA起始扇区号(这里读第2个扇区,MBR本身是第0扇区)

注:你的USB设备总共有15618048个扇区,所以LBA范围是0x00到0xE90FFF(15618047的十六进制)。

第三步:调用INT 0x13功能0x42读取扇区

把DAP的内存地址放到si寄存器,然后触发扩展调用:

; 执行扇区读取
mov ah, 0x42
mov dl, 0x80        ; USB驱动器号
mov si, dap         ; 指向DAP结构的地址
int 0x13
jc read_error       ; CF置位=读取失败

完整MBR示例代码

下面是一个简化的MBR代码,实现从USB读取第2个扇区到0x7E00并跳转执行:

org 0x7C00
bits 16

start:
    ; 初始化实模式段寄存器
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00  ; 栈顶设为MBR起始地址

    ; 检查LBA扩展支持
    mov ah, 0x41
    mov bx, 0x55AA
    mov dl, 0x80
    int 0x13
    jc no_lba
    cmp bx, 0xAA55
    jne no_lba

    ; 调用扩展读扇区功能
    mov ah, 0x42
    mov si, dap
    int 0x13
    jc read_fail

    ; 读取成功,跳转到读取的扇区执行
    jmp 0x0000:0x7E00

no_lba:
    mov si, msg_no_lba
    call print_str
    jmp $  ; 死循环

read_fail:
    mov si, msg_read_fail
    call print_str
    jmp $

; 实模式字符串打印函数
print_str:
    mov ah, 0x0E
.loop:
    lodsb
    or al, al
    jz .done
    int 0x10
    jmp .loop
.done:
    ret

; 提示信息
msg_no_lba db "BIOS不支持LBA扩展!", 0x0D, 0x0A, 0
msg_read_fail db "USB扇区读取失败!", 0x0D, 0x0A, 0

; DAP结构定义
dap:
    db 0x10
    db 0
    dw 1
    dw 0x7E00
    dw 0
    dq 1

; MBR结束标志
times 510-($-$$) db 0
dw 0xAA55

关键注意事项

  • 驱动器号适配:如果你的USB不是第一个存储设备,可能需要调整dl的值(比如0x81对应第二个设备),部分BIOS会自动把启动USB设为0x80,保险起见可以做个简单遍历检测(0x80到0x8F)。
  • 内存地址限制:实模式下只能访问1MB以下内存,所以缓冲区要放在0x7C00之后的安全区域,避免覆盖MBR本身。
  • 错误码排查:INT 0x13调用失败时,ah寄存器会返回错误码(比如0x01=无效命令,0x02=扇区未找到),可以根据错误码针对性排查问题。

内容的提问来源于stack exchange,提问作者石原秀一

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:33:22