你好世界引导加载程序不工作

发布于 2024-08-28 12:42:28 字数 360 浏览 4 评论 0原文

我一直在学习此网页上的教程,逐步创建一个显示的引导加载程序你好世界。

第二个教程(我们尝试输出“A”)工作得很好,但第一个教程对我来说根本不起作用! (BIOS 完全忽略软盘并直接引导至 Windows)。尽管任何解释都将不胜感激,但这不是什么问题。

真正的问题是我无法让第三个教程工作。相反,在输出“Hello World”时,我在屏幕的左下角看到了一个不寻常的字符(和闪烁的光标)。它看起来有点像圆角矩形内的笑脸。有谁知道如何让 Hello World 按预期显示?

I've been working through the tutorials on this webpage which progressively creates a bootloader that displays Hello World.

The 2nd tutorial (where we attempt to get an "A" to be output) works perfectly, and yet the 1st tutorial doesn't work for me at all! (The BIOS completely ignores the floppy disk and boots straight into Windows). This is less of an issue, although any explanations would be appreciated.

The real problem is that I can't get the 3rd tutorial to work. Instead on outputting "Hello World", I get an unusual character (and blinking cursor) in the bottom-left corner of the screen. It looks a bit like a smiley face inside a rounded rectangle. Does anyone know how to get Hello World to display as it should?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

无声无音无过去 2024-09-04 12:42:28

你说“直接启动进入Windows”,所以我假设你使用的是物理PC。未来需要注意的是:始终使用模拟器进行开发!这更容易。我喜欢 Bochs 的 OSDeving,因为它有很好的调试功能。现在,讨论可能的解决方案。

有很多有缺陷的 BIOS 违反了 IBM PC 对 0x7C00 加载地址的非正式规范。

当你进行汇编时,这可能会带来很多内存地址等问题。因此,让开头看起来像这样:

[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;this tells the assembler where the code will be loaded at when it runs on your machine. It uses this to compute the absolute addresses of labels and such.

jmp word 0:flush ;#FAR jump so that you set CS to 0. (the first argument is what segment to jump to. The argument(after the `:`) is what offset to jump to)
;# Without the far jmp, CS could be `0x7C0` or something similar, which will means that where the assembler thinks the code is loaded and where your computer loaded the code is different. Which in turn messes up the absolute addresses of labels.
flush: ;#We go to here, but we do it ABSOLUTE. So with this, we can reset the segment and offset of where our code is loaded.
mov BP,0 ;#use BP as a temp register
mov DS,BP ;#can not assign segment registers a literal number. You have to assign to a register first.
mov ES,BP ;#do the same here too
;#without setting DS and ES, they could have been loaded with the old 0x7C0, which would mess up absolute address calculations for data. 

看,一些负载在 0x07C0:0000 处,而大多数负载(及其被认为是正确的)在 0x0000:7C00 处。这是相同的平面地址,但不同的段设置确实会搞砸绝对内存地址。因此,让我们消除汇编器的“魔力”,看看它是什么样子(注意我不保证地址完全正确。我不知道所有操作码的大小)

jmp word 0:0x7C04 ;# 0x7C04 is the address of the `flush` label 
...

所以,我们跳转到一个绝对地址。

现在那么。如果我们不这样做会发生什么?

以这个程序为例:

mov ax,[mydata]
hlt

mydata: dw 500 ;#just some data

这会反汇编成类似

mov ax,[0x7C06] 

哦,它使用绝对寻址,那么怎么会出错呢?那么,如果 DS 实际上是 0x7C0 呢?然后,它不会得到汇编器期望的 0:0x7C06 ,而是得到 0x7C0:0x7C06 ,它们不是相同的平面地址。

我希望这有助于您理解。但这确实是一个复杂的主题,需要一段时间的低级编程才能完全理解。

You say "boot straight into windows" so I assume you are using a physical PC. Future note to make: Always use an emulator for development! It's just easier. I like Bochs for OSDeving cause it has nice debugging features. Now, onto the possible solution.

There are a lot of buggy BIOSes that break the informal specifications of the IBM PC for the 0x7C00 load address.

This can give a lot of problems with memory addresses and such whenever you are assembling. So make the beginning look like this:

[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;this tells the assembler where the code will be loaded at when it runs on your machine. It uses this to compute the absolute addresses of labels and such.

jmp word 0:flush ;#FAR jump so that you set CS to 0. (the first argument is what segment to jump to. The argument(after the `:`) is what offset to jump to)
;# Without the far jmp, CS could be `0x7C0` or something similar, which will means that where the assembler thinks the code is loaded and where your computer loaded the code is different. Which in turn messes up the absolute addresses of labels.
flush: ;#We go to here, but we do it ABSOLUTE. So with this, we can reset the segment and offset of where our code is loaded.
mov BP,0 ;#use BP as a temp register
mov DS,BP ;#can not assign segment registers a literal number. You have to assign to a register first.
mov ES,BP ;#do the same here too
;#without setting DS and ES, they could have been loaded with the old 0x7C0, which would mess up absolute address calculations for data. 

See, some load at 0x07C0:0000 and most load(and its considered proper to) at 0x0000:7C00. It is the same flat address, but the different segment settings can really screw up absolute memory addresses. So let's remove the "magic" of the assembler and see what it looks like (note I don't guarantee addresses to be completely correct with this. I don't know the size of all opcodes)

jmp word 0:0x7C04 ;# 0x7C04 is the address of the `flush` label 
...

So, we jump to an absolute address.

Now then. What happens when we don't do this?

take this program for example:

mov ax,[mydata]
hlt

mydata: dw 500 ;#just some data

This disassembles to something like

mov ax,[0x7C06] 

Oh, well it uses absolute addressing, so how could that go wrong? Well, what if DS is actually 0x7C0 ? then instead of getting the assembler expected 0:0x7C06 it will get 0x7C0:0x7C06 which are not the same flat address.

I hope this helps you to understand. It's really a complicated topic though and takes a while of low level programming to fully understand.

那一片橙海, 2024-09-04 12:42:28

我认为这个问题很可能与指定的来源有关。

[ORG 0x7C00]    ;Origin, tell the assembler that where the code will

根据我们一直以来的对话,该地址似乎在某种程度上与预期不符。可能只是 DS 数据段寄存器不是您所期望的。实际上,您可能可以通过在调用之前添加 ds 的 push 和 pop 来从网页获取原始列表,这样显示字符串,

 push cs
 pop ds

如果不能,则以下代码可以工作。

 [ORG 0x000]    ; switched to 0 since we are going to try to correct it ourself

 call nextinstruction
 nextinstruction:    ; get the return address of the call into dx
 pop dx              ; which is essentially the start of the code + 3 (3 bytes for the call instruction)
 MOV SI, HelloString ;Store string pointer to SI
 add si, dx          ; add IP from start of program
 sub si, 3           ; subtract the 3 the call instruction probably took
 push cs
 pop ds              ; make ds the same as cs.  
 CALL PrintString   ;Call print string procedure
 JMP $      ;Infinite loop, hang it here.

该代码计算出正在运行的代码在运行时的偏移量,并确保 DS 指向同一段。除非另有说明,涉及SI的指令通常也使用DS作为其代码段来引用存储器。

DS 是一个段寄存器,您可能需要阅读类似 组装艺术了解更多信息。

Earlz 也在做同样的事情,只是确保寄存器正确,以便正确引用内存地址。只是他比我更了解引导扇区的细节。

I think the problem is likely to be related to the origin specified.

[ORG 0x7C00]    ;Origin, tell the assembler that where the code will

Based on the conversation we've been having it appears that the address isn't as predicted in some way. It might simply that DS the data segment register is not what you expect. You might actually be able to get the original listing from the web page to work by adding a push and pop of ds before the call to display the string like this,

 push cs
 pop ds

If not the following code works.

 [ORG 0x000]    ; switched to 0 since we are going to try to correct it ourself

 call nextinstruction
 nextinstruction:    ; get the return address of the call into dx
 pop dx              ; which is essentially the start of the code + 3 (3 bytes for the call instruction)
 MOV SI, HelloString ;Store string pointer to SI
 add si, dx          ; add IP from start of program
 sub si, 3           ; subtract the 3 the call instruction probably took
 push cs
 pop ds              ; make ds the same as cs.  
 CALL PrintString   ;Call print string procedure
 JMP $      ;Infinite loop, hang it here.

This code figures out the offset at runtime of the code being run and also makes sure DS is point to the same segment. Unless otherwise noted instructions involving SI generally also use DS as their code segment to reference the memory.

DS is a segment register and you might want to read something like the Art of Assembly to learn more.

Earlz is also doing the same sort of thing, just making sure the registers are correct so that the memory address is referenced correctly. It's just he knows more about the boot sector specifics than me.

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