Assembly I';我构建自己的引导加载程序,当我使用qemu模拟它时,我得到;引导失败:无法读取引导磁盘";
我正在构建自己的引导加载程序,当我使用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
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实现的模拟器上,您可能会侥幸逃脱,但我要说,在真正的硬件上,这是危险的@科迪格雷:他不依赖它。他使用远JMPJMP 0x0000:start
将CS设置为0x0000,因此在该点之后依赖CS是完全安全的。当然,他可以把远JMP作为第一条指令,因为他没有使用BPB。对,当然。应该更加注意代码。我没注意到那是一次跳远。你知道你在期待什么。感谢您的澄清。非常感谢您的帮助,Michael PetchI仍然收到“引导失败:无法从引导磁盘读取”错误,我无法找出它是什么