我正在尝试制作一个非常基本的 2 阶段引导加载程序,但在阅读第二阶段时遇到了问题。当我尝试将int 13h
与ah = 2
一起使用时,中断失败,返回码为1(无效命令(。我正在使用 nasm 编译并使用 qemu 进行测试。我一直在测试它是否使用 qemu 的控制台来检查地址0x8C00
并查看ax
和携带标志。我总是看到0x8C00
周围的内存被归零,ax = 0x0101
并设置了进位标志。
引导加载程序。
[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
第二阶段
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 返回"无效命令"错误,因为您要求加载不存在的磁盘扇区 0。在CHS表示法中,C的ylinder数从0开始,Head数从0开始,但Setor数从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