【问题标题】:Bootloader/kernel only booting in a virtual machine引导加载程序/内核仅在虚拟机中引导
【发布时间】:2016-11-24 22:13:22
【问题描述】:

所以,过去几周我一直在研究用汇编 (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

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

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

【问题讨论】:

  • 我没有看过你那里的代码,因为它需要我点击一个链接......但是,如果代码不提供 BIOS 参数块,我可以告诉你我绝对见过真正的硬件比虚拟机更挑剔。确保您的 BPB 格式正确,看看是否有帮助。
  • 我已经尝试添加一个 BIOS 参数块,它并没有真正改变任何东西。
  • 请将相关代码内嵌为minimal reproducible example
  • 你在哪个硬件上?我已经看到了华硕的疯狂(尽管在其他系统中也有奇怪的地方。)我发现最起码的事情会吓坏华硕的机器。
  • 验证您的硬件是否允许传统的 MBR 引导而不需要 EFI 也是值得的。如果 UEFI 被配置为要求,您将永远无法使用该引导扇区引导它。

标签: assembly x86 bootloader osdev floppy


【解决方案1】:

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

  1. 当 BIOS 跳转到您的代码时,您不能依赖具有有效或预期值的 CS、DS、ES、SS、SP 寄存器。当您的引导加载程序启动时,它们应该被适当地设置。您只能保证您的引导加载程序将从物理地址 0x00007c00 加载和运行,并且引导驱动器号已加载到 DL 寄存器中。

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

MOV DL, 0x0 ;drive 0 = floppy 1

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-10
    • 2021-10-12
    • 2011-02-01
    • 1970-01-01
    • 2020-05-31
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多