assembly - Hello World 引导加载程序不工作

标签 assembly x86 bootstrapping bootloader

我一直在学习教程 on this webpage它逐步创建一个显示 Hello World 的引导加载程序。

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

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

最佳答案

您说“直接启动到 Windows”,所以我假设您使用的是物理 PC。 future 注意事项:始终使用模拟器进行开发!这更容易。我喜欢 Bochs for 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分别是 不是 同一个单位地址。

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

关于assembly - Hello World 引导加载程序不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2630899/

相关文章:

c - 为什么这个内联汇编不能为每条指令使用单独的 asm volatile 语句?

assembly - 在 Windows 中学习汇编编程的任何来源?

architecture - 将ARM指令转换为i386指令

c++ - 使用 SSE 内部函数时结果不正确

javascript - 如何通过 PHP 将 "disabled"按钮设置回 "enabled"?

java - 两个数字之间的 "compare"如何在机器级别实现?

assembly - 无法让 16 位汇编程序跳转到 0x1000 :0x0000

assembly - x86 汇编程序崩溃,可能忽略简单错误

Angular 2引导主要组件不起作用

assembly - 如何用bios中断13h写入硬盘