Bootloader 可以在模拟器中运行,但不能在真实硬件上运行

Posted

技术标签:

【中文标题】Bootloader 可以在模拟器中运行,但不能在真实硬件上运行【英文标题】:Bootloader works in emulators but not on real hardware 【发布时间】:2017-06-14 04:13:18 【问题描述】:

我正在用汇编语言编写一个引导加载程序,它似乎在 qemu、bochs 和 virtualbox 上运行良好。但是,它并没有在真实硬件上加载内核(似乎)。

引导加载程序首先将一个字符写入视频内存(用于调试),然后从驱动器读取扇区 2 并远跳转到内核。然后内核将一些字符写入显存。

在真机上,我在屏幕上看到引导加载程序中的字符,然后它挂起(闪烁的插入符号)。

我已尝试将 DS、ES、SI 设置为零,并且我也在设置堆栈段。

我正在使用 bios int 13 函数 2 从驱动器中读取扇区 2。我有点怀疑它与驱动器号有关。我都尝试使用在启动时(在 dl 中)传递给引导加载程序的驱动器号,并将其手动设置为 0x0、0x80 和 0x81。

我注意到的一件奇怪的事情是,我用来接近跳跃的标签神奇地获得了正确的地址。使用 objdump 我看到例如:jmp 0x2,而使用 gdb 和 qemu,它说:jmp 0x7c02。 CS 和所有其他段寄存器都为零。无论我在链接中使用 -Ttext 0x0 还是 -Ttext 0x7c00,引导加载程序在所有模拟器上都可以正常工作。当我与 -Ttext 0x7c00 链接时,objdump 说 jmp 0x7c02。

编辑,引导加载程序如下所示:

.code16
.text
movw $0xb800, %ax
movw %ax, %ds
movw $0x0741, (0x0)

xorw %ax, %ax
movw %ax, %ds
movw %ax, %si
movw %ax, %es

movw  $0x8000, %ax
movw  %ax, %ss
movw  $0, %sp

movb $2, %ah
movb $1, %al
movw $0x02, %cx
movb $0x00, %dh

movw $0x5000, %bx
movw %bx, %es
movw $0x0, %bx
int $0x13

ljmpw $0x5000, $0x0000

编辑,第二阶段:

.code16
.text
    movw $0xb800, %ax
    movw %ax, %ds
    movw $0x0742, (0x2)

forever:
    jmp forever

【问题讨论】:

如果使用了相对跳跃,则近距离跳跃将起作用。 很抱歉,我们无法为您提供这么少的信息。您能否使用足够的代码制作第二个引导加载程序来演示手头的问题并向我们展示? 尝试通过拆分成更小的部分来解决它。如果您在加载第 2 扇区之前打印一个字符,则在加载后打印另一个字符(并且读取调用是否返回错误会有所不同)。将您的代码与可用的开源引导加载程序进行比较;也许他们做了一些你错过的设置。您是否按照 Ralf Brown 中断列表在通话前进行了适当的设置? 您应该检查错误代码并在错误时打印另一个字符。还显示加载的第二个扇区的开始。显然,还要确保所说的第二个扇区实际上已写入您的物理设备,也许在跳转到它之前从其中打印一个字符。 movw $0x074b, (0x1) 似乎是错误的。每个单元格为 2 个字节。你的意思是movw $0x074b, (0x2) 【参考方案1】:

如果您的硬件对 USB 驱动器使用软盘仿真,则可能在您的 MBR 中没有正确的 BIOS Parameter Block (BPB) 时,它可能无法正常启动。许多 BIOS 将尝试在引导加载程序启动时检测 BPB,甚至可能在引导加载程序加载到内存后使用正确的驱动器几何形状更新值。可能您的引导加载程序没有被检测为正确的可引导驱动器,或者它是但 BIOS 在执行之前用驱动器几何信息覆盖了您的一些代码。

下面添加了一个看起来像 2.88MB 软盘的 BPB。

.global _start
.code16
.text

_start:
    jmp     main
    .space 3 - (.-_start)

    /* Configuration for a 2.88MB floppy using FAT 12 */
    OEMname:            .ascii      "MYBOOT  "
    bytesPerSector:     .word       512
    sectPerCluster:     .byte       1
    reservedSectors:    .word       1
    numFAT:             .byte       2
    numRootDirEntries:  .word       240
    numSectors:         .word       5760
    mediaType:          .byte       0xf0
    numFATsectors:      .word       9
    sectorsPerTrack:    .word       36
    numHeads:           .word       2
    numHiddenSectors:   .long       0
    numSectorsHuge:     .long       0
    driveNum:           .byte       0
    reserved:           .byte       0x00
    signature:          .byte       0x29
    volumeID:           .long       0x54428E71
    volumeLabel:        .ascii      "NO NAME    "
    fileSysType:        .ascii      "FAT12   "

main:
    movw $0xb800, %ax
    movw %ax, %ds
    movw $0x0741, (0x0)

    xorw %ax, %ax
    movw %ax, %ds
    movw %ax, %si
    movw %ax, %es

    movw  $0x8000, %ax
    movw  %ax, %ss
    movw  $0, %sp

    movb $2, %ah
    movb $1, %al
    movw $0x02, %cx
    movb $0x00, %dh

    movw $0x5000, %bx
    movw %bx, %es
    movw $0x0, %bx
    int $0x13

    ljmpw $0x5000, $0x0000

.space 510-(.-_start)
.word 0xaa55

【讨论】:

以上是关于Bootloader 可以在模拟器中运行,但不能在真实硬件上运行的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 可以构建项目但不能在模拟器上运行

为啥应用内购买方法可以在模拟器上完美运行,但不能在真实设备 iOS 6 上运行?

Fetch on Core Data 可以在模拟器上运行,但不能在设备上运行

应用程序可以在模拟器上完美运行,但不能在物理设备上[在iOS 13.3.1上]

Android Studio 应用程序可在模拟器中运行,但不能在真实设备上运行

模拟器中的 iPhone 应用程序可在一台 Mac 上运行,但不能在另一台 Mac 上运行