操作系统的引导加载程序不起作用

发布于 2024-09-10 12:32:55 字数 1342 浏览 10 评论 0原文

我正在制作一个自定义操作系统。我有两个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

放低过去 2024-09-17 12:32:55

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

...
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! 后,它应该执行其他操作(至少应该停止),否则不要当你遇到未定义的行为或挂断时感到惊讶......

Of course it prints two exclamation marks. Let's look at your code:

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

Note: I added some arrows that illustrate how program execution proceeds.

The first two lines are responsible for printing the final ! after you've already output Hello, World. This is achieved via a call to your PrintCharacter sub-procedure. (arrows 1 and 2.) When PrintCharacter returns (arrow 3), your program simply continues straight onwards (arrow 4)... and the next line of code happens to be the beginning of PrintCharacter again. Since the AL 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 actually CALL PrintCharacter, there is no defined place to return to, so it returns to... some undefined place, most probably (arrow 5). 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...

人疚 2024-09-17 12:32:55

我不知道 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 认为您的磁盘不可启动。

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:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文