加载自定义内核会导致 VM 不断重启

Loading a custom kernel causes VM to constantly reboot

我正在开发一个自定义的 32 位 OS,并且我编写了一个基本的引导加载程序。我试图让它加载一个简单的内核,将一个字符放到屏幕上,但是,我没有得到字符,而是得到了一个三重错误(也许?)

我试过增加读取的扇区数、扩展程序中“db 0”的数量、篡改编译脚本...

没有,但是,如果成功读取磁盘,我的 OS 也会打印字母 'H',有时当我将扇区数量增加到指数级时,vm 不会重新启动,但没有成功读取磁盘。

Github: https://github.com/Nutty000/Broken-OS

jmp ExtendedSpace之后执行的第一条指令是db 'H'即不是代码

"BROKEN-OS",你说?

您的GitHubldr.asm文件有很多错误。
引导扇区和 BPB 结构使用了所有错误的数据大小!难怪您的 VM 会变得很混乱。

                                            should be
                                            ---------  
OEMIdentifier               db "POSv0.10"
BytesPerSector              dd 512            DW
SectorsPerCluster           db 1
ReservedSectors             db 32             DW
NumberOfFATs                db 2
NUmberOfRootDirEntries      db 224            DW
NumberOfSectors             dd 2880           DW
MediaDescriptorType         db 0xf0
SectorsPerFAT               db 9              DW
SectorsPerTrack             db 18             DW
NumberOfSides               db 2              DW
HiddenSectors               db 0              DD
LargeSectorCount            db 0              DD

DriveNumber             db 0x00
                        db 0
Signature               db 0x29
VolumeID                db 0x00, 0x00, 0x00, 0x00
VolumeLabel             db "POSBOOTDSK "
SystemIdentifier        db "FAT12   "

jmp short mbrcodestart

这个短跳转是用 2 字节编码的,但是上面提到的结构必须从引导扇区的偏移量 3 开始。您需要使用 nop 指令进行填充,或强制执行 near (non-short) jmp.

jmp short mbrcodestart
nop

将大写字母“H”存储为您稍后跳转到的 [ExtendedSpace] 的第一个字节是个坏主意,但幸运的是,这不会造成问题,因为特定编码 72 恰好是对应于有效的 one-byte 指令 dec ax.


还有:

  • 没有自己设置段寄存器
  • 没有在其他扇区无法覆盖的安全位置设置堆栈
  • 忽略 BIOS.Teletype 调用的 BHBL 参数
  • 不检查从 int 13h 调用中获得的进位标志
  • 一次读取多个扇区,而不是使用循环读取单个扇区的更可靠方法。 (有些 real-world BIOS 有点损坏;仅使用最简单的功能就可以让您的引导加载程序即使在此类机器上也能正常工作。另请参阅 。)
  • ...

所有这一切都发生在进入保护模式之前。在尝试更进一步之前,首先确保实模式部分工作正常。

这个论坛上有很多解决这些问题的好答案:

您目前的ldr.asm供参考:

[org 0x7c00]

jmp short mbrcodestart

OEMIdentifier               db "POSv0.10"
BytesPerSector              dd 512
SectorsPerCluster           db 1
ReservedSectors             db 32
NumberOfFATs                db 2
NUmberOfRootDirEntries          db 224
NumberOfSectors             dd 2880
MediaDescriptorType         db 0xf0     ;3.5 Inch Double-Sided HD Floppy disk(1.44MB or 2.88MB) should work with single-sided ones as well, maybe even 5.25 inch diskettes
SectorsPerFAT               db 9
SectorsPerTrack             db 18
NumberOfSides               db 2
HiddenSectors               db 0
LargeSectorCount            db 0

;EBPB

DriveNumber             db 0x00 ;Floppy Disk
                    db 0    ;Reserved
Signature               db 0x29
VolumeID                db 0x00, 0x00, 0x00, 0x00
VolumeLabel             db "POSBOOTDSK "
SystemIdentifier            db "FAT12   "

mbrcodestart:

mov bx, POSBL_WelcomeString
call print16
call read16

mov ah, 0x0e
mov al, [ExtendedSpace]
int 0x10


jmp ExtendedSpace

POSBL_WelcomeString:
    db "PlanetOS BootLoader (POSBL) v0.1 (limited compatability)",0

print16:
    mov ah, 0x0e
    loop:
        mov al, [bx]
        cmp al, byte 0
        je exit
        int 0x10
        inc bx
        jmp loop
    exit:
        ret
    
ExtendedSpace equ 0x7e00

read16:
    mov ah, 0x02
    mov al, 20
    mov bx, ExtendedSpace
    mov ch, 0x00
    mov cl, 0x02
    mov dh, 0x00
    mov dl, 0x00
    int 0x13
    ret


times 510-($-$$) db 0
dw 0xaa55