从驱动器读取扇区失败

Reading Sector From Drive Fails

我正在尝试制作一个非常基本的两阶段引导加载程序,但我 运行 遇到读取第二阶段的问题。当我尝试将 int 13hah = 2 一起使用时,中断失败并显示 return 代码 1(无效命令)。我正在使用 nasm 进行编译并使用 qemu 进行测试。我一直在测试它是否可以使用 qemu 的控制台来检查地址 0x8C00 并查看 ax 和进位标志。我总是看到0x8C00周围的内存被归零,ax = 0x0101并且设置了进位标志。

bootloader.s

[org 0x7c00]
[bits 16]
mov [driveNum], dl
mov ah, 0x0A
mov al, '-'
mov cx, 80
int 0x10
;read drive
mov ax, 0
mov es, ax
mov ah, 2
mov al, 1 ;sectors to read
mov ch, 0 ;cylinder
mov cl, 0 ;sector
mov dh, 0 ;head
mov dl, byte [driveNum] ; drive
mov bx, 0x8c00

int 13h


hang:
jmp $

driveNum: db 0xAA
times (510 - ($ - $$)) db 0
db 0x55
db 0xAA

secondstage.s

jmp $
times 512 db 0xFF

编译为

nasm -f bin bootloader.s -o bootloader
nasm -f bin secondstage.s -o secondstage
cat bootloader secondstage > boot

运行 使用

qemu-system-x86_64 -fda boot

问题 1(由 Michael Petch 解决)

BIOS returns 出现 "Invalid Command" 错误,因为您要求加载不存在的磁盘扇区 0。在 CHS 符号中 Cylinder数字从 0 开始,Head 数字从 0 开始,但是 Sector 数字从 1 开始。
包含引导加载程序的扇区位于 (0,0,1)。如果您的第二阶段位于下一个更高的扇区(但如果您选择的话,它可以在其他任何地方!)那么您需要请求扇区 (0,0,2)。

mov cx, 0002h    ;Cylinder 0, Sector 2

问题2

您假设 DS 段寄存器指向您的引导加载程序是危险的。在这方面您不能相信 BIOS!您唯一可以假设的是,您的引导加载程序位于线性地址 0000h:7C00h 的内存中,并且 DL 寄存器保存引导驱动器的代码。

因为你写了 [org 0x7c00] 缺少的设置是设置 DS=0

xor ax, ax             <<===
mov ds, ax             <<===
mov [driveNum], dl

问题 3

视频 BIOS 功能 "WriteCharacterAtCursorPosition" 还需要 BH 中的显示页码,如果视频模式是图形模式,则还需要 BL 中的颜色。请不要依赖任何您没有检查过的注册内容。只需要写:

mov ax, 0A00h + '-'
mov bx, 0007h          <<===
mov cx, 80
int 10h

jmp $
times 512 db 0xFF

这将创建 514 个字节,比一个完整的扇区多 2 个字节。您的引导加载程序将读取 1 个 512 字节的扇区。从技术上讲,这里没有错误,但这可能表明存在一些误解。

jmp $
times (512 - ($ - $$)) db 255