PAYATHON 2026

INT 13h AH=02h 返回 AH=09h,如何读取到物理地址 0x20000?

数据小许

结论

可以将扇区读到物理地址 0x20000。第二段代码中的 ES:BX 实际指向 0x1FF00,而不是 0x20000。读取 512 字节时,缓冲区会跨过 64 KiB 边界,传统 BIOS 磁盘服务通常会因此返回 AH=09h(DMA 边界错误)。

为什么偏移量为 0 仍会出错

在 x86 实模式下,ES:BX 对应的物理地址按以下公式计算:

physical address = ES × 16 + BX

第二段代码将 ES 设为 0x1FF0,BX 设为 0,所以目标物理地址是:

0x1FF0 × 16 + 0 = 0x1FF00

一个扇区有 512 字节。缓冲区从 0x1FF00 开始,延伸到 0x200FF,因此会跨过 0x20000 处的 64 KiB 边界。传统 BIOS 磁盘读取通常要求单次读取的数据不跨越 64 KiB DMA 边界,否则可能返回 AH=09h。

BX=0 表示段内偏移为零,并不代表物理地址为零或正好是 0x20000。物理地址由 ES 和 BX 共同决定。

读取到物理地址 0x20000

将段地址设为 0x2000,偏移设为 0 即可:

mov ah, 0x02
mov al, 1
mov ch, 2
mov cl, 12
mov dh, 1
mov dl, drive_number  ; 使用实际的 BIOS 驱动器号
mov bx, 0x2000
mov es, bx
mov bx, 0x0000
int 0x13

此时 ES:BX 对应的物理地址是 0x2000 × 16 + 0 = 0x20000。从这个边界开始读取一个 512 字节扇区,不会跨越下一个 64 KiB 边界。

代码中的 drive_number 是说明用的占位符。实际程序应在 DL 中传入目标驱动器号。题目片段没有展示 DL 的设置,因此假定调用前已经正确设置,或由代码补上。

多扇区读取时

多扇区读取时,也要检查整个缓冲区是否跨越 64 KiB 边界。对于常见的 512 字节扇区,可以用以下方式检查段内偏移和读取长度:

offset + sector_count × 512 <= 0x10000

如果读取范围会越界,可以拆成多次读取,或改用不会跨界的缓冲区。具体行为可能因 BIOS 实现而异;还应确保 CHS 参数有效,并遵守目标 BIOS 对单次读取扇区数的限制。

备注:内容仅供参考。