2010-07-19 67 views
4

我正在制作自定义操作系统。我有两个NASM文件:OS的引导加载程序不起作用

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 

当我从VirtualBox中的软盘映像启动时,它显示2个感叹号而不是一个,它甚至不能在QEmu(Q.app)中启动。我是操作系统开发新手,所以如果有人能告诉我我做错了什么并给我一些关于如何更好地设置我的操作系统的指导,那将是非常好的。

回答

5

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

... 
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 

注:我加了一些箭头是说明如何执行程序进行。你已经输出Hello, World

前两行负责打印最终!。这是通过致电PrintCharacter子程序来实现的。 (箭头12)。当PrintCharacter返回时(箭头3),程序直接继续向前(箭头4)...并且下一行代码恰好是PrintCharacter的开始。由于AL寄存器仍然包含33(即,代码为!的ANSI代码),因此会打印另一个感叹号。

然后,执行再次到达RET,但这个时候,因为你实际上并没有CALLPrintCharacter,没有定义的地方返回,所以返回......一些不确定的地方,最有可能(箭头5)。我想这就是你的操作系统在启动过程中停止的瞬间。

结论:你的代码打印Hello, World!后,应该做其他事(至少应该停止),否则,当你得到了一个未定义的行为或挂起不要感到惊讶......

+0

谢谢。我将无限循环移至start.asm,现在它工作。但是QEmu仍然无法启动。 – None 2010-07-20 01:37:59

+0

我不了解QEMU。我只能猜测:也许你的第一条指令('INT 0x13h')是罪魁祸首。可能是因为QEMU的寄存器在启动时设置不同,并且中断调用不能满足您的需求。尝试明确设置寄存器('AH = 02,AL = 01,...')。或者QEMU没有模拟你的软盘驱动器,因此无法加载你的启动程序。 - 我必须承认,我不明白你在'boot.asm'中究竟做了什么。你不应该加载'start.asm'到内存中,然后*跳转*到它吗? – stakx 2010-07-20 09:02:15

+0

当我将boot.asm的主要内容放在boot.asm中时,它工作正常。 – None 2010-07-20 18:22:01

1

我不知道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 

兑换= notrunc之外告诉“DD”说它不应该截断磁盘,即删除它并用你的二进制文件覆盖它,status = noxfer使它不那么冗长,seek = 1将start.bin写入磁盘的第二个扇区(从0开始)。

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

因此,最后,您使用start.bin作为磁盘映像调用qemu(MyOS.img在最后的'dd'命令后成为它的副本),并且由于您尚未使用启动签名start.bin结束时,qemu BIOS不认为您的磁盘是可启动的。