从驱动器读取扇区失败
Reading Sector From Drive Fails
我正在尝试制作一个非常基本的两阶段引导加载程序,但我 运行 遇到读取第二阶段的问题。当我尝试将 int 13h
与 ah = 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
我正在尝试制作一个非常基本的两阶段引导加载程序,但我 运行 遇到读取第二阶段的问题。当我尝试将 int 13h
与 ah = 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