Assembly I';我构建自己的引导加载程序,当我使用qemu模拟它时,我得到;引导失败:无法读取引导磁盘";

Assembly I';我构建自己的引导加载程序,当我使用qemu模拟它时,我得到;引导失败:无法读取引导磁盘";,assembly,x86,bootloader,osdev,real-mode,Assembly,X86,Bootloader,Osdev,Real Mode,我正在构建自己的引导加载程序,当我使用qemu模拟它时,我得到“引导失败:无法读取引导磁盘”。它是这样工作的:第一阶段加载第二阶段,然后第二阶段引导加载程序加载内核。一切看起来都很好,但我一直在得到这个信息,没有什么事情像它应该的那样有效 org 0x500 ; Print 'a'. mov ax, 0x0E61 int 0x10 cli hlt ; Pad image to multiple of 512 bytes. times ((0

我正在构建自己的引导加载程序,当我使用qemu模拟它时,我得到“引导失败:无法读取引导磁盘”。它是这样工作的:第一阶段加载第二阶段,然后第二阶段引导加载程序加载内核。一切看起来都很好,但我一直在得到这个信息,没有什么事情像它应该的那样有效

org 0x500

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

    cli
    hlt

    ; Pad image to multiple of 512 bytes.

times ((0x200 - 2) - ($ - $$)) db 0x00
这是我的第一阶段引导加载程序的代码: 我正在构建自己的引导加载程序,当我使用qemu模拟它时,我得到“引导失败:无法读取引导磁盘”

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

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:
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
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
org 0x500

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

    cli
    hlt

    ; Pad image to multiple of 512 bytes.

times ((0x200 - 2) - ($ - $$)) db 0x00
您应该将
开始
放在
字符串
定义之后,以便正确设置所有段

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

如果你阅读拉尔夫·布朗的中断列表,你会发现:

磁盘-将扇区读入内存

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
返回:

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.asm
boot2.asm
中,您错误地设置了AH。AH应为值2,以执行磁盘读取

boot2.asm
中,您读取了错误的扇区号。你有:

    mov cl, 2
您想从磁盘读取第三个扇区。应该是:

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

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:
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
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
org 0x500

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

    cli
    hlt

    ; Pad image to multiple of 512 bytes.

times ((0x200 - 2) - ($ - $$)) db 0x00
boot2.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:
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
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
org 0x500

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

    cli
    hlt

    ; Pad image to multiple of 512 bytes.

times ((0x200 - 2) - ($ - $$)) db 0x00
kernel.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:
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
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
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而不是QEMU。BOCHS有一个内置的调试器,它非常支持像bootloader这样的实模式代码


引导加载程序提示
我有一个Stackoverflow答案,其中有许多。

我使用的是mike file.txt,然后我使用linux中的make all terminator在第一阶段中,我正在内存中加载第二阶段。在第2阶段,我应该读取磁盘,对吗?这就是我的makefile.txt中的内容。在初始化其他段寄存器时,依赖
CS
的值不是也不明智吗?在具有相对“干净”、“正确”BIOS实现的模拟器上,您可能会侥幸逃脱,但我要说,在真正的硬件上,这是危险的@科迪格雷:他不依赖它。他使用远JMP
JMP 0x0000:start
将CS设置为0x0000,因此在该点之后依赖CS是完全安全的。当然,他可以把远JMP作为第一条指令,因为他没有使用BPB。对,当然。应该更加注意代码。我没注意到那是一次跳远。你知道你在期待什么。感谢您的澄清。非常感谢您的帮助,Michael PetchI仍然收到“引导失败:无法从引导磁盘读取”错误,我无法找出它是什么