我写了一个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并且屏幕被清除但是之后我的内核没有做任何事情
我觉得有些不对劲。任何人都可以帮助我吗?
答案 0 :(得分:2)
鉴于您的原始问题,如果读取的扇区中至少没有一个扇区的数据,那么您所读取的磁盘就不会在多个仿真器上工作(在这种情况下扇区是512字节)。如果尝试从磁盘映像读取不完整的扇区,仿真器磁盘读取通常会返回某种类型的错误。
为了解决这个问题,我经常只需创建一个1.44MB的磁盘映像,其中包括:
dd if=/dev/zero of=XordaOS.img bs=1024 count=1440
这将创建一个1024 * 1440字节的零填充文件,大小为1.44MB软盘。许多模拟器将自动从这样的文件大小确定磁盘类型,这是一个奖励。然后,您需要将引导加载程序和内核的每个部分添加到映像中,而不是在每次写入后将其截断(使用 DD ' 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的一些想法。