6

在过去的一周里,我一直在开发一个简单的操作系统,用于学习目的和......“有趣”。VirtualBox 和 NASM 并驾齐驱,我实际上有了一个不错的开始。最终,我决定我还想通过臭名昭著的Brokenthorn 教程来开发一个引导加载程序(在非常困难地撞到 512 字节的墙之后) ,直到从文件系统加载为止。

通过一些 HexFiend 恶作剧和一些空白的 FAT16 图像,我最终得到了 BPB。通过一些额外的组装黑客(基础是 Brokenthorn 的教程,第 6 部分),我还使用我的引导加载程序加载文件,它从我的虚拟磁盘加载恰当命名的“引导”文件(使用 dd if=/dev/zero of=boot.img bs=512 计数=2880)

那么,那是什么问题呢?这是我通过 USB 记忆棒加载到实际硬件时所看到的(在本例中为 /dev/disk3,其中编译的文件是 boot.bin):

dd bs=512 count=1 if=compiled/boot.bin of=/dev/disk3

这是预期的输出(在 VirtualBox 中):

电流输出

实际输出相比(在旧笔记本电脑上)

旧输出

'-' indicates a sector is being loaded
'_' indicates a sector was loaded
'!' indicates all of the desired sectors were loaded properly
'R' indicates a read error
'T' indicates the FAT table is being loaded
'D' indicates the FAT table was loaded properly
'F' means the file is being located (or Found, hence the F)
'L' means the file is being loaded

(我会使用实际的调试消息,但 512 字节的限制非常可怕。)

所以,区别在于一个是 U 盘,一个是(虚拟)软盘。它们都加载了完全相同的信息,包括 BPB。但是,一种有效,一种无效。这是我加载扇区的代码的主要部分(使用 ah 02h/int 13h,我听说它适用于 USB):

ReadSectors:
    mov di, 0x0005                  ; How many times should we retry the read?

ReadSectors.loop:
    ; DEBUG
    push ax
    mov ah, 0eh
    mov al, '-'
    int 10h
    pop ax
    push ax
    push bx
    push cx
    call LBAToCHS
    mov ah, 02h                     ; Set the interrupt to the 
                                    ; 'read sector' function
    mov al, 1                       ; Only read one sector
    mov ch, byte[chs.track]         ; The track to read from
    mov cl, byte[chs.sector]        ; The sector to read from
    mov dh, byte[chs.head]          ; The head to read from
    mov dl, byte[_bpb.driveNumber]  ; The drive to read from
    int 13h                         ; Call our 'disk IO' interrupt
    jnc ReadSectors.success         ; If we successfully read the data, 
                                    ; we don't have to try again
    mov ah, 00h                     ; Set the interrupt to the 
                                    ; 'reset disk' function
    int 13h                         ; Call our 'disk IO' interrupt
    dec di                          ; Decrement our error counter
    pop cx
    pop bx
    pop ax
    jnz ReadSectors.loop            ; Try again if we've failed
    jmp ReadSectors.fail            ; RED ALERT

(完整的源代码,包括 BPB,可以在 Pastebin ( http://pastebin.com/SeUm7xu6 )上找到

到目前为止,我已经克服了 Assembly 的许多问题,但这个问题让我很难过。希望我能尽快通过引导加载程序并抽象文件 IO。

任何建议将不胜感激。提前致谢!

4

1 回答 1

6

您的代码从驱动器号 0 读取,这可能不是从设备引导加载程序加载的设备(如果您从 USB 记忆棒引导,通常不是)。您应该读取的驱动器号由 BIOS 加载到dl寄存器中。这已经是关于 SO的已回答问题。

于 2012-04-04T10:46:30.543 回答