实模式下用汇编读硬盘

2025-04-16  本文已影响0人  GTMYang

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


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

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

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


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. 进阶优化

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

上一篇 下一篇

猜你喜欢

热点阅读