我正在构建自己的引导加载程序,当我使用 qemu 模拟它时,我得到 "Boot failed: could not read the boot disk"

I'm building my own bootloader and when I emulate it using qemu I get "Boot failed: could not read the boot disk"

我正在构建自己的引导加载程序,当我使用 qemu 模拟它时,我得到 "Boot failed: could not read the boot disk"。它是这样工作的:第一阶段加载第二阶段,然后第二阶段引导加载程序加载内核。一切看起来都很好,但我不断收到该消息,但没有任何效果。

这是我的第一阶段引导加载程序的代码: 我正在构建自己的引导加载程序,当我使用 qemu 模拟它时,我得到 "Boot failed: could not read the boot disk".

org 0x7C00
jmp 0x0000:start

string db 'Bootloader by JCLC - GMM4 - RGT!', 13, 10, 0

    start:
    ;Setup stack segments
    mov ax,cs              
    mov ds,ax  
    mov es,ax              
    mov ss,ax
    mov sp, 0x7c00

    xor ax, ax
    mov ds, ax

    xor ax, ax
    mov ds, ax
    mov si, string
    mov cl, 0

    printString:
    lodsb                                
    cmp cl, al                          
    je done

    mov ah, 0xe    
    mov bl, 2      
    int 10h            

    jmp printString

    done:

    mov ah, 0x02
    mov al, 1
    mov dl, 0x80
    mov ch, 0
    mov dh, 0   
    mov cl, 2
    mov bx, 0x7E00
    int 0x13

    jmp 0x7E00  

    times ((0x200 - 2) - ($ - $$)) db 0x00
    dw 0xAA55

这是我的第二阶段引导加载程序的代码:

org 0x7E00

    mov ax,cs              
    mov ds,ax  
    mov es,ax              
    mov ss,ax
    mov sp,0x7E00

    xor ax, ax
    mov ds, ax    

    mov ah, 0x500
    mov al, 1
    mov dl, 0x80
    mov ch, 0
    mov dh, 0   
    mov cl, 2
    mov bx, 0x500
    int 0x13

    jmp 0x500 

    times ((0x200 - 2) - ($ - $$)) db 0x00
    dw 0xAA55

这应该是内核。这只是我写的东西,看看是否一切正常。

org 0x500

    ; Print 'a'.
    mov ax, 0x0E61
    int 0x10

    cli
    hlt

    ; Pad image to multiple of 512 bytes.

times ((0x200 - 2) - ($ - $$)) db 0x00

您的代码有很多问题。你在原来的 boot1.asm:

中有这个
    jmp 0x0000:start
string db 'Bootloader by JCLC - GMM4 - RGT!', 13, 10, 0
    ;Setup stack segments
    mov ax,cs              
    mov ds,ax  
    mov es,ax              
    mov ss,ax
    mov sp, 0x7c00
start:

您应该将 start 紧跟在 string 定义之后,以便正确设置所有段。

当 BIOS 将控制权转移到引导加载程序时 DL 包含可用于磁盘操作的引导驱动器编号 Int 13h/AH=2 (磁盘读取)。使用 mov dl, 0x80 对驱动器编号进行硬编码会强制您始终从硬盘 1 启动(0x00 = 软盘 A,0x01 = 软盘 B,0x80 = 硬盘 1,0x81 = 硬盘 2)。您可以简单地从第一和第二阶段磁盘读取中删除 mov dl, 0x80,因为您不会在任何时候破坏 DL,它仍然是 BIOS 传递的值。

如果您阅读 Ralph Brown 的 Int 0x13/AH=2 中断列表,您会发现:

DISK - READ SECTOR(S) INTO MEMORY

AH = 02h
AL = number of sectors to read (must be nonzero)
CH = low eight bits of cylinder number
CL = sector number 1-63 (bits 0-5)
     high two bits of cylinder (bits 6-7, hard disk only)
DH = head number
DL = drive number (bit 7 set for hard disk)
ES:BX -> data buffer

Return:

CF set on error
if AH = 11h (corrected ECC error), AL = burst length
CF clear if successful
AH = status (see #00234)
AL = number of sectors transferred (only valid if CF set for some BIOSes)

在您的 boot1.asmboot2.asm 中,您错误地设置了 AHAH 应该是做磁盘读取的值 2。

boot2.asm中你读错了扇区号。你有:

    mov cl, 2

您想从磁盘读取第 3 个扇区。应该是:

    mov cl, 3

考虑到所有这些,您的文件将如下所示:

boot1.asm:

org 0x7C00
jmp 0x0000:start

string db 'Bootloader by JCLC - GMM4 - RGT!', 13, 10, 0

    start:    
    ;Setup stack segments
    mov ax,cs
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov sp, 0x7c00

    mov si, string
    mov cl, 0

    printString:
    lodsb
    cmp cl, al
    je done

    mov ah, 0xe
    mov bl, 2
    int 10h

    jmp printString

    done:

    mov ah, 2       ; Int 13h/AH=2 = disk read
    mov al, 1
    ;mov dl, 0x80   ; Comment out - use value passed by BIOS in DL
    mov ch, 0
    mov dh, 0
    mov cl, 2
    mov bx, 0x7E00
    int 0x13

    jmp 0x7E00

    times ((0x200 - 2) - ($ - $$)) db 0x00
    dw 0xAA55

boot2.asm:

org 0x7E00

    mov ax,cs
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov sp,0x7E00

    xor ax, ax
    mov ds, ax

    mov ah, 2        ; Int 13h/AH=2 = disk read 
    mov al, 1
    ; mov dl, 0x80   ; Comment out - use value passed by BIOS in DL
    mov ch, 0
    mov dh, 0
    mov cl, 3        ; You want to read sector 3 (not 2)
    mov bx, 0x500
    int 0x13

    jmp 0x500

    times ((0x200 - 2) - ($ - $$)) db 0x00
    dw 0xAA55

kernel.asm:

org 0x500

    ; Print 'a'.
    mov ax, 0x0E61
    int 0x10

    cli
    hlt

    ; Pad image to multiple of 512 bytes.

times ((0x200 - 2) - ($ - $$)) db 0x00

当我通过你的 Makefile 运行 时,我将其作为 QEMU:

的输出


调试引导加载程序

调试引导加载程序的最佳工具是 BOCHS 而不是 QEMUBOCHS 有一个内置的调试器,对引导加载程序等实模式代码有很好的支持。


引导加载程序提示

我有一个包含 个数的 Whosebug 答案。