[英]I'm building my own bootloader and when I emulate it using qemu I get “Boot failed: could not read the boot disk”
我正在構建自己的引導程序,當我使用qemu對其進行仿真時,我得到“引導失敗:無法讀取引導盤”。 它的工作方式如下:第一階段加載第二階段,然后第二階段引導加載程序加載內核。 一切看起來都很好,但是我一直在收到該消息,但沒有任何工作像它應該的那樣。
這是我的第一階段引導程序的代碼:我正在構建自己的引導程序,當我使用qemu模擬它時,我得到“引導失敗:無法讀取引導盤”。
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
這就是內核。 這只是我寫的文章,以查看Everythig是否按預期工作。
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
有此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:
您應該在string
定義之后start
,以便正確設置所有段。
當BIOS將控制權轉移到引導加載程序時, DL包含可用於磁盤操作的引導驅動器號,例如Int 13h / AH = 2 (磁盤讀取)。 用mov dl, 0x80
硬編碼驅動器號mov dl, 0x80
強制您始終從硬盤1引導(0x00 =軟盤A,0x01 =軟盤B,0x80 =硬盤1,0x81 =硬盤2)。 您可以簡單地從第一級和第二級磁盤讀取中刪除mov dl, 0x80
,因為您在任何時候都不會銷毀DL ,它仍然是BIOS傳遞的值。
如果您閱讀拉爾夫·布朗的Int 0x13 / AH = 2的中斷列表,則會發現:
磁盤-將扇區讀入內存
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
:
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
運行此Makefile
,將其作為QEMU中的輸出輸出:
調試引導程序的最佳工具是BOCHS而不是QEMU 。 BOCHS具有一個內置的調試器,該調試器對諸如引導程序之類的實模式代碼有很好的支持。
我有一個Stackoverflow答案,其中包含許多Bootloader開發技巧 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.