4

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

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

开始.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 个感叹号而不是 1 个,甚至在 QEmu (Q.app) 中也无法启动。我是操作系统开发的新手,所以如果有人能告诉我我做错了什么并给我一些关于如何更好地设置我的操作系统的指导,那就太好了。

4

2 回答 2

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,但这一次,由于您实际上CALL PrintCharacter没有返回,因此没有定义的位置可以返回,所以它返回到......一些未定义的位置,很可能(箭头5)。我想那是您的操作系统停止继续启动过程的那一刻。

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

于 2010-07-19T23:13:34.360 回答
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

conv=notrunc 告诉'dd'它不应该截断磁盘,也就是说,删除它并用你的二进制文件覆盖它,status=noxfer 使它不那么冗长,seek=1 将 start.bin 写入磁盘的第二个扇区(以 0 开头)。

要验证我的意思,请尝试创建一个 1MB 的磁盘映像,然后使用您正在使用的命令(即 dd),您会看到磁盘映像已缩减为二进制文件的副本。

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

于 2011-11-01T03:18:23.237 回答