Bootloader/kernel 仅在虚拟机中启动

Bootloader/kernel only booting in a virtual machine

所以,过去几周我一直在研究用汇编语言编写引导加载程序和内核 (x86/x86_64),虽然我尝试了更复杂的解决方案,但在自己编写一个之前,我决定尝试一些代码名为 Sinned 的用户发布了 here。我的引导程序代码是:

[BITS 16]
[ORG 0x7C00]

MOV DL, 0x0 ;drive 0 = floppy 1
MOV DH, 0x0 ;head (0=base)
MOV CH, 0x0 ;track/cylinder
MOV CL, 0x02 ;sector (1=bootloader, apparently sectors starts counting at 1 instead of 0)
MOV BX, 0x1000 ;place in RAM for kernel - I suppose randomly chosen on examples
MOV ES, BX ;place BX in pointer ES
MOV BX, 0x0 ;back to zero - also has something to do with RAM position

ReadFloppy:
MOV AH, 0x02
MOV AL, 0x01
INT 0x13
JC ReadFloppy ;if it went wrong, try again

;pointers to RAM position (0x1000)
MOV AX, 0x1000
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX

JMP 0x1000:0x0

;assuming we get never back here again, so no further coding needed (kernel handles everything now)

TIMES 510 - ($ - $$) db 0 ;fill resting bytes with zero
DW 0xAA55 ;end of bootloader (2 bytes)

我的内核文件是:

;set print-registers
MOV AH, 0x0E ;function nr
MOV BH, 0x00 ;page
MOV BL, 0x07 ;color

MOV SI, msg ;move msg to SI-pointer
CALL PrintString ;call function to print SI (msg)

JMP $ ;hang

PrintString:
.next_char:
MOV AL, [SI] ;current character
OR AL, AL
JZ .print_done ;if current char is zero, go to end
INT 0x10 ;print character
INC SI ;increase pointer to msg (next character)
JMP .next_char
.exit_char
RET

msg db 'Hello world from the kernel!', 13, 10, 0

TIMES 512 - ($ - $$) db 0 ;fill the rest

我可以让一切都变得很好assemble,当连接到软盘控制器时,单个二进制文件在 VirtualBox 中创建引导。虽然这让我有信心在自己的加载程序和内核上工作,但我希望在裸机上启动它时感到满意。

我已尝试使用 USB 驱动器启动映像但无济于事,而且我确定我正在正确地映像 USB 记忆棒。我开始觉得我在这里遗漏了一些非常明显的东西。我怀疑这与使用 13h 从 "floppy" 读取有关,我实际上是在尝试从 USB 读取原始二进制文件。是这样吗?如果是这样,我如何重写引导加载程序以从非特定磁盘而不是软盘读取?

我写了一些适用于此代码的 。特别是我有这个提示:

  1. When the BIOS jumps to your code you can't rely on CS,DS,ES,SS,SP registers having valid or expected values. They should be set up appropriately when your bootloader starts. You can only be guaranteed that your bootloader will be loaded and run from physical address 0x00007c00 and that the boot drive number is loaded into the DL register.

第一张软盘的引导驱动器通常为 0,因此您的虚拟机可能工作正常,因为您引导了一张安装为虚拟驱动器 A: 的软盘映像。导致您出现问题的代码在您的 ReadFloppy 代码中。特别是这一行:

MOV DL, 0x0 ;drive 0 = floppy 1

您在应该使用 BIOS 传递的值的地方硬编码为零。在任何您以软盘驱动器 A 以外的任何方式引导的系统上:它可能会失败。要解决此问题,只需 删除 上面的行。

我建议查看我在 link 中提供的其他引导加载程序提示。