为什么我的bootloader没有加载我的内核

时间:2017-10-14 18:43:54

标签: assembly kernel system x86-16 bootloader

我写了一个bootloader和一个内核,希望我的bootloader加载我的内核

[org 0x7c00]

    jmp     start

    ;%include "console.inc"

start:
    xor     ax, ax
    mov     ds, ax

    ;call    init_console
    ;call    clrscr

    ;mov     si, head
    ;mov     ah, 0x0f
    ;call    str_out

    ;mov     si, prompt
    ;mov     ah, 0x0f
    ;call    str_out

wait_in:
    in      al, 0x60

    cmp     al, 0
    jg      end_wait_in

    jmp     wait_in

end_wait_in:
    mov     ax, 0
    int     0x13

    jc      end_wait_in

read:
    mov     ax, 0x8000
    mov     es, ax
    mov     bx, 0

    mov     ah, 2
    mov     al, 1
    mov     ch, 0
    mov     cl, 2
    mov     dh, 0
    int     0x13

    jc      read

    jmp     0x8000:0x0000

head:        db          'XordaOS Bootloader v0.0.1', 0xa, 0xa, 0x0
prompt:      db          'Press any key to boot', 0x0

times 510 - ($ - $$) db 0
db 0x55
db 0xaa

这是我的引导程序,现在是我的内核

    jmp     start

    %include "console.inc"

start:
    xor     ax, ax
    mov     ds, ax

    call    init_console
    call    clrscr

    mov     si, msg
    mov     ah, 0x0f
    call    str_out

    cli
    jmp     $

msg:        db          'Hello World', 0x0

这是console.inc(在loader.asm中用所有控制台代码注释)

init_console:
    mov     ax, 0xb800
    mov     es, ax
    xor     bx, bx
    xor     dx, dx

    ret

str_out:
    lodsb
    cmp     al, 0x0
    je      str_out_end

    cmp     al, 0xa
    je      new_line

    mov     [es:bx], ax
    add     bx, 2

    jmp     str_out

new_line:
    add     dx, 160
    mov     cx, dx
    sub     dx, bx
    add     bx, dx
    mov     dx, cx

    jmp     str_out

str_out_end:

    ret

clrscr:
    mov     cx, 2000
    xor     bx, bx

    mov     al, ' '
    mov     ah, 0x00        

start_clr:
    mov     [es:bx], ax
    add     bx, 2

    loop    start_clr

    xor     bx, bx

    ret

然后我输入了以下命令:

#!/bin/bash

nasm -fbin -o loader.bin loader.asm
nasm -fbin -o kernel.bin kernel.asm

dd if=/dev/zero of=XordaOS.img bs=1024 count=1440
dd if=loader.bin of=XordaOS.img bs=512 seek=0 conv=notrunc
dd if=kernel.bin of=XordaOS.img bs=512 seek=1 conv=notrunc

然后我在QEMU Launcher(GUI)中启动它

一切正常,直到我加载内核的代码区域。 在end_wait_in之后我调用了我的清除屏幕功能clrscr并且屏幕被清除但是之后我的内核没有做任何事情

我觉得有些不对劲。任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:2)

鉴于您的原始问题,如果读取的扇区中至少没有一个扇区的数据,那么您所读取的磁盘就不会在多个仿真器上工作(在这种情况下扇区是512字节)。如果尝试从磁盘映像读取不完整的扇区,仿真器磁盘读取通常会返回某种类型的错误。

为了解决这个问题,我经常只需创建一个1.44MB的磁盘映像,其中包括:

dd if=/dev/zero of=XordaOS.img bs=1024 count=1440

这将创建一个1024 * 1440字节的零填充文件,大小为1.44MB软盘。许多模拟器将自动从这样的文件大小确定磁盘类型,这是一个奖励。然后,您需要将引导加载程序和内核的每个部分添加到映像中,而不是在每次写入后将其截断(使用 DD &#39; s conv=notrunc选项。您可以使用以下方法执行此操作:< / p>

dd if=loader.bin of=XordaOS.img bs=512 seek=0 conv=notrunc 
dd if=kernel.bin of=XordaOS.img bs=512 seek=1 conv=notrunc

使用Int 13h/ah=2h进行磁盘读取 DL 是驱动器号。在您的代码中,通过在 DL 中放置0将其硬编码为0。您应该考虑使用 DL 中BIOS传递给引导加载程序的值。您可以保存该值并在需要磁盘操作时将其还原。因为它是你的代码只适用于驱动器0(通常是软盘A :)。

当您最终将内核加载到0x8000:0x0000并且 FAR JMP 时,您需要确保正确设置 DS 。在这种情况下,您需要在 DS 中使用0x8000。

我有一些bootloader tips您可能希望考虑其中一些。

要调试实模式引导加载程序和其他16位实模式代码,我建议使用BOCHS,它具有正确的实模式调试支持。您可以使用 QEMU 进行远程调试,但它有局限性和缺陷。您可以在我的其他Stackoverflow答案中获得debugging 16-bit code in QEMU的一些想法。