Assembly 为什么';我的引导加载程序不能加载我的内核吗

Assembly 为什么';我的引导加载程序不能加载我的内核吗,assembly,kernel,system,x86-16,bootloader,Assembly,Kernel,System,X86 16,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

我编写了一个引导加载程序和一个内核,希望我的引导加载程序加载我的内核

[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
这是我的引导程序,现在是我的内核

[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中注释了所有控制台代码)

然后我输入了以下命令:

#!/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启动器(GUI)中启动了它

在我加载内核的代码区之前,一切都正常工作。 在end_wait_in之后,我调用了我的clear screen函数clrsc,屏幕被清除,但在那之后,我的内核什么也不做


我觉得有点不对劲。有人能帮我吗?

鉴于您最初的问题,如果读取的扇区中没有至少一个扇区的数据(在本例中,扇区是512字节),那么您正在执行的磁盘读取在许多模拟器上都不起作用。如果试图从磁盘映像中读取不完整的扇区,Emulator磁盘读取通常会返回某种类型的错误

为了解决这个问题,我通常只创建一个1.44MB的磁盘映像,其中包含以下内容:

dd if=/dev/zero of=XordaOS.img bs=1024 count=1440
这将创建一个1024*1440字节的零填充文件,大小为1.44MB软盘。许多模拟器将根据这样的文件大小自动确定磁盘类型,这是一个额外的好处。然后,您需要将引导加载程序和内核的每个部分添加到映像中,而不在每次写入后截断它(使用DD的
conv=notrunc
选项)。您可以通过以下方法完成此操作:

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
当用DL读取磁盘时,驱动器号。在代码中,通过将0放置在DL中,将其硬编码为0。您应该考虑使用DL中BIOS传递给Bootloader的值。您可以保存该值并在磁盘操作所需的时候恢复它。因为您的代码只在驱动器0(通常是软盘A:)上工作。

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

我有一些你可能要考虑的问题。


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

我没有尝试运行它(或在过去10年中完成汇编),但你不是总是在读取开始时将bx重置为0,从而将内核的所有内容加载到同一字节吗?@JakubJudas他一次读取了整个内核。学会使用调试器并检查内核是否已加载。另外,显示
init_console
str_out
的代码。你设置了D吗S在内核中注册?我怀疑您没有并且正在从错误的段和偏移量读取字符串。您是否将内核中的DS设置为0x8000?作为Jester请求的补充,您是否可以发布整个
console.inc