操作系统的引导加载程序不起作用
我正在制作一个自定义操作系统。我有两个 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
当我从 VirtualBox 中的软盘映像启动时,它显示 2 个感叹号而不是一个,它甚至无法在 QEmu (Q.app) 中启动。我是操作系统开发的新手,所以如果有人能告诉我我做错了什么并给我一些关于如何更好地设置操作系统的指导,那就太好了。
I am making a custom Operating System. I have two nasm files:
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
I compile them into .bin files using these commands:
nasm boot.asm -f bin -o boot.bin
nasm start.asm -f bin -o start.bin
Then add them to a floppy image with these commands:
dd if=boot.bin bs=512 of=MyOS.img count=1
dd if=start.bin bs=512 of=MyOS.img count=2
When I boot from the floppy image in VirtualBox it shows 2 exclamation points instead of one and it doesn't even boot in QEmu (Q.app). I am new to Operating System development and so It would be nice if someone could tell me what I did wrong and give me some pointers on how to better set up my OS.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当然它会打印两个感叹号。让我们看看你的代码:
前两行负责在输出
Hello, World 之后打印最终的!
。这是通过调用PrintCharacter
子过程来实现的。 (箭头1
和2
。)当PrintCharacter
返回时(箭头3
),您的程序将直接继续前进(箭头4
)...下一行代码恰好又是PrintCharacter
的开头。由于AL
寄存器仍包含 33(即!
的 ANSI 代码),因此会打印另一个感叹号。然后,执行再次到达
RET
,但这一次,由于您实际上没有CALL
PrintCharacter
,因此没有定义返回的位置到,所以它返回到...某个未定义的地方,很可能是(箭头5
)。我想那是您的操作系统停止继续启动过程的那一刻。结论:在代码打印
Hello, World!
后,它应该执行其他操作(至少应该停止),否则不要当你遇到未定义的行为或挂断时感到惊讶......Of course it prints two exclamation marks. Let's look at your code:
The first two lines are responsible for printing the final
!
after you've already outputHello, World
. This is achieved via a call to yourPrintCharacter
sub-procedure. (arrows1
and2
.) WhenPrintCharacter
returns (arrow3
), your program simply continues straight onwards (arrow4
)... and the next line of code happens to be the beginning ofPrintCharacter
again. Since theAL
register still contains 33 (ie. the ANSI code for!
), another exclamation mark is printed.Then, execution once again gets to
RET
, but this time, since you didn't actuallyCALL
PrintCharacter
, there is no defined place to return to, so it returns to... some undefined place, most probably (arrow5
). I suppose that's the instant where your OS stops continuing with the boot process.Conclusion: After your code prints
Hello, World!
, it should do something else (it should at least stop), otherwise don't be surprised when you get undefined behaviour or a hang-up...我不知道 VirtualBox 如何启动您的代码,但我很确定 qemu 不会,因为您以错误的方式在磁盘映像上设置二进制文件。当您在磁盘映像上使用“dd”时,需要向其传递一个选项,以便它不会截断磁盘,如下所示:
conv=notrunc 告诉“dd”它不应截断磁盘,也就是说,删除它并用二进制文件覆盖它,status=noxfer 使其不那么冗长,seek=1 将 start.bin 写入磁盘的第二个扇区(从 0 开始)。
为了验证我所说的,请尝试创建一个 1MB 的磁盘映像,并使用您正在使用的命令(即 dd),您将看到磁盘映像已缩小为二进制文件的副本。
因此,最后,您使用 start.bin 作为磁盘映像来调用 qemu(MyOS.img 在最后一个“dd”命令后成为它的副本),并且因为您在启动结束时没有使用启动签名。 bin,qemu BIOS 认为您的磁盘不可启动。
I don't know how VirtualBox is booting your code, but I'm pretty sure qemu doesn't because you are setting up the binaries on the disk image in the wrong way. When you're using 'dd' on the disk image, you need to pass it an option, so that it doesn't truncate the disk, something like this:
conv=notrunc tells 'dd' that it should not truncate the disk, that is, delete it and overwrite it with your binary, status=noxfer makes it less verbose and seek=1 writes start.bin to the second sector of the disk (starts with 0).
To verify what i'm saying, try creating a disk image of 1MB, and use the command (i.e. dd) you were using and you'll see that the disk image is reduced to a copy of your binary.
So, in the end, you call qemu using start.bin as a disk image (MyOS.img becomes a copy of it after the last 'dd' command), and since you have not used a boot signature at the end of start.bin, the qemu BIOS does not think your disk is bootable.