X86 操作系统&x27;s引导加载程序没有';行不通

X86 操作系统&x27;s引导加载程序没有';行不通,x86,kernel,nasm,bootloader,osdev,X86,Kernel,Nasm,Bootloader,Osdev,我正在制作一个定制的操作系统。我有两个nasm文件: boot.asm: [BITS 16] ;tell the assembler that its a 16 bit code [ORG 0x7C00] ;Origin, tell the assembler that where the code will ;be in memory after it is been loaded INT 0x13 JMP $ ;infinite loop TIMES 510 -

我正在制作一个定制的操作系统。我有两个nasm文件:

boot.asm:

[BITS 16]   ;tell the assembler that its a 16 bit code
[ORG 0x7C00]    ;Origin, tell the assembler that where the code will
;be in memory after it is been loaded

INT 0x13

JMP $       ;infinite loop

TIMES 510 - ($ - $$) db 0   ;fill the rest of sector with 0
DW 0xAA55           ; add boot signature
start.asm:

[BITS 16]
MOV AL, 72
CALL PrintCharacter
MOV AL, 101
CALL PrintCharacter
MOV AL, 108
CALL PrintCharacter
MOV AL, 108
CALL PrintCharacter
MOV AL, 111
CALL PrintCharacter
MOV AL, 44
CALL PrintCharacter
MOV AL, 32
CALL PrintCharacter

MOV AL, 87
CALL PrintCharacter
MOV AL, 111
CALL PrintCharacter
MOV AL, 114
CALL PrintCharacter
MOV AL, 108
CALL PrintCharacter
MOV AL, 100
CALL PrintCharacter
MOV AL, 33
CALL PrintCharacter

PrintCharacter: 
MOV AH, 0x0E
MOV BH, 0x00
MOV BL, 0x07
INT 0x10
RET

TIMES 512 - ($ - $$) db 0
我使用以下命令将它们编译成.bin文件:

nasm boot.asm -f bin -o boot.bin
nasm start.asm -f bin -o start.bin
dd if=boot.bin bs=512 of=MyOS.img count=1
dd if=start.bin bs=512 of=MyOS.img count=2
然后使用以下命令将它们添加到软盘映像:

nasm boot.asm -f bin -o boot.bin
nasm start.asm -f bin -o start.bin
dd if=boot.bin bs=512 of=MyOS.img count=1
dd if=start.bin bs=512 of=MyOS.img count=2

当我从VirtualBox中的软盘映像启动时,它会显示两个感叹号而不是一个感叹号,而且它甚至不会在QEmu(Q.app)中启动。我是操作系统开发新手,如果有人能告诉我我做错了什么,并给我一些如何更好地设置操作系统的建议,那就太好了。

当然,它会打印两个感叹号。让我们看看您的代码:

...
MOV AL, 33
CALL PrintCharacter    ;   |1
                       ;   |          ^     |4
PrintCharacter:        ;   v    |2    |     |
MOV AH, 0x0E           ;        |     |     |
MOV BH, 0x00           ;        |     |     |
MOV BL, 0x07           ;        |     |     |
INT 0x10               ;        |     |     |     5
RET                    ;        v     |3    v     ----> off to la-la land
注意:我添加了一些箭头来说明程序执行是如何进行的

前两行负责打印最终的
在您已经输出了
你好,World
之后。这是通过调用
PrintCharacter
子过程实现的。(箭头
1
2
)当
PrintCharacter
返回时(箭头
3
),您的程序将直接继续(箭头
4
)。。。下一行代码恰好又是
PrintCharacter
的开头。由于
AL
寄存器仍然包含33(即
的ANSI代码),因此会打印另一个感叹号

然后,执行再次到达
RET
,但这次,由于您实际上没有调用
PrintCharacter
,因此没有定义的返回位置,因此它返回到。。。一些未定义的位置,很可能(箭头
5
)。我想这就是操作系统停止继续引导过程的时刻


结论:在您的代码打印后
你好,世界,它应该做一些其他的事情(至少应该停止),否则当您出现未定义的行为或挂断时,请不要感到惊讶…

我不知道VirtualBox是如何引导您的代码的,但我非常确定qemu不会,因为您在磁盘映像上以错误的方式设置二进制文件。当您在磁盘映像上使用'dd'时,需要向其传递一个选项,以便它不会截断磁盘,如下所示:

dd if=boot.bin of=MyOS.img bs=512 count=1 conv=notrunc status=noxfer
dd if=start.bin of=MyOS.img bs=512 count=1 conv=notrunc seek=1 status=noxfer
conv=notrunc告诉'dd'它不应该截断磁盘,也就是说,删除它并用二进制文件覆盖它,status=noxfer使它不那么冗长,seek=1将start.bin写入磁盘的第二个扇区(从0开始)

要验证我的说法,请尝试创建1MB的磁盘映像,并使用您正在使用的命令(即dd),您将看到磁盘映像已缩减为二进制文件的副本


因此,最后,您使用start.bin作为磁盘映像调用qemu(MyOS.img在最后一个'dd'命令后成为它的副本),并且由于您没有在start.bin末尾使用引导签名,qemu BIOS认为您的磁盘不可引导。

谢谢。我将无限循环移动到start.asm,现在它可以工作了。但它仍然不能用QEmu启动。我不知道QEmu。我只能猜测:也许你的第一条指令(
int0x13h
)就是罪魁祸首。可能是QEMU在启动时设置了不同的寄存器,而中断调用并不能满足您的需要。尝试显式设置寄存器(
AH=02,AL=01,
)。或者QEMU没有模拟您的软盘驱动器,因此无法加载您的启动程序。-我必须承认我不明白你在
boot.asm
中到底在做什么。您是否应该将
start.asm
加载到内存中,然后跳转到它?当我将start.asm的主要内容放入boot.asm中时,它工作正常。接下来,您需要做的是:将代码放入
boot.asm
中,将包含
start.asm
中代码的扇区加载到内存中(例如,通过调用
int13h
函数)将其加载到某个固定地址(在
start.asm
中使用
ORG
指定该地址。然后,在加载该代码后,跳转到该地址。
start.bin
在VirtualBox中运行,因为它不会像QEMU那样执行磁盘签名检查。