美文网首页
实模式下用汇编读硬盘

实模式下用汇编读硬盘

作者: GTMYang | 来源:发表于2025-04-16 10:43 被阅读0次

x86 实模式(16位) 下,可以使用 BIOS 中断 INT 0x13 来读取硬盘数据。以下是详细步骤和示例代码:


1. 硬盘读取原理(CHS/LBA模式)

(1) CHS(柱面-磁头-扇区)模式

  • 参数
    • 柱面(Cylinder)CL(低6位) + CH(完整8位)
    • 磁头(Head)DH
    • 扇区(Sector)CL(高2位)
  • 限制
    • 最大支持 8GB(1024柱面 × 256磁头 × 63扇区 × 512字节)。

(2) LBA(逻辑块寻址)模式

  • 参数
    • LBA 地址:28位(最大支持 128GB)。
    • 使用 INT 0x13 扩展功能(AH=0x42)。

2. BIOS 中断 INT 0x13 功能

功能号(AH) 功能 参数
AH=0x02 读扇区(CHS) AL=扇区数, CH=柱面, CL=扇区, DH=磁头, DL=驱动器号, ES:BX=缓冲区
AH=0x42 读扇区(LBA) DL=驱动器号, DS:SI=磁盘地址包(DAP)

3. 示例代码(CHS模式读取扇区)

以下代码演示如何 读取硬盘的第一个扇区(MBR) 到内存 0x7E00

org 0x7C00          ; 引导扇区加载到 0x7C00
bits 16

start:
    mov ax, 0x07C0
    mov ds, ax      ; 设置数据段
    mov es, ax      ; 设置附加段(用于缓冲区)

    ; 读取硬盘扇区(CHS模式)
    mov ah, 0x02    ; 功能号:读扇区
    mov al, 1       ; 读取1个扇区
    mov ch, 0       ; 柱面0
    mov cl, 1       ; 扇区1(注意:扇区从1开始)
    mov dh, 0       ; 磁头0
    mov dl, 0x80    ; 驱动器号(0x80=第一块硬盘)
    mov bx, 0x7E00  ; ES:BX = 目标缓冲区(0x7E00)

    int 0x13        ; 调用BIOS中断
    jc error        ; 如果CF=1,表示出错

    ; 成功读取后,数据在 0x7E00
    jmp success

error:
    mov si, err_msg
    call print_string
    hlt

success:
    mov si, succ_msg
    call print_string
    hlt

print_string:
    lodsb           ; 加载字符到AL
    or al, al       ; 检查是否结束(AL=0)
    jz .done
    mov ah, 0x0E    ; BIOS打印字符功能
    int 0x10
    jmp print_string
.done:
    ret

err_msg db "Error reading disk!", 0
succ_msg db "Disk read success!", 0

times 510-($-$$) db 0
dw 0xAA55          ; MBR签名

4. 示例代码(LBA模式读取扇区)

LBA模式需要 磁盘地址包(DAP),支持更大容量的硬盘:

org 0x7C00
bits 16

start:
    mov ax, 0x07C0
    mov ds, ax
    mov es, ax

    ; 设置DAP(Disk Address Packet)
    mov si, dap
    mov ah, 0x42    ; 功能号:扩展读(LBA)
    mov dl, 0x80    ; 驱动器号(0x80=第一块硬盘)
    int 0x13
    jc error
    jmp success

dap:
    db 0x10         ; DAP大小(16字节)
    db 0            ; 保留
    dw 1            ; 扇区数
    dw 0x7E00       ; 目标偏移(ES:BX)
    dw 0            ; 目标段(ES)
    dd 0            ; LBA低32位(从0开始)
    dd 0            ; LBA高32位(支持48位LBA)

error:
    mov si, err_msg
    call print_string
    hlt

success:
    mov si, succ_msg
    call print_string
    hlt

print_string:
    lodsb
    or al, al
    jz .done
    mov ah, 0x0E
    int 0x10
    jmp print_string
.done:
    ret

err_msg db "Error reading disk!", 0
succ_msg db "Disk read success!", 0

times 510-($-$$) db 0
dw 0xAA55

5. 关键注意事项

  1. 驱动器号
    • 0x80 = 第一块硬盘
    • 0x81 = 第二块硬盘
  2. 扇区编号
    • CHS模式下,扇区从1开始(不是0)。
  3. 缓冲区对齐
    • 确保 ES:BX 指向的缓冲区 不跨越64KB边界
  4. 错误处理
    • 检查 CF(进位标志),如果 CF=1,表示出错(错误代码在 AH)。

6. 进阶优化

  • 使用 LBA48:支持更大硬盘(需检测 BIOS 是否支持)。
  • DMA 传输:提高读取速度(需切换保护模式)。
  • 保护模式读取:通过 ATA PIO 直接与硬盘控制器通信。

如果需要更高级的硬盘操作(如写入、分区表解析),可以进一步探讨!

相关文章

网友评论

      本文标题:实模式下用汇编读硬盘

      本文链接:https://www.haomeiwen.com/subject/mixebjtx.html