我在VMWare和Bochs上运行操作系统 Boot 加载程序时遇到问题。
Boot 加载程序应该通过int 10h
显示一个字符串,但它只是打印背景颜色,没有任何字符。
颜色由bx
的值设置。代码在这里:
org 7c00h
; org 0100h
mov ax, cs
mov ds, ax
mov es, ax
call DispStr
jmp $
DispStr:
mov ax, BootMessage
mov bp, ax
mov cx, 13
mov ax, 1301h
mov bx, 005eh
mov dh, 3
mov dl, 0
int 10h
ret
BootMessage: db "Hello, Luser!"
times 510-($-$$) db 0
dw 0xaa55
字符串
2条答案
按热度按时间3phpmpom1#
虽然这个答案很晚,但问题很简单,代码是一个很好的例子,说明开发人员假设BIOS跳转到具有有效或预期值的代码。我最近回答了一些关于 * bootloader * 的问题,并开始提供一般提示。Tip#1应该适用于这里:
1.当BIOS跳转到您的代码时,您不能依赖具有有效或预期值的 CS、DS、ES、SS、SP 寄存器。它们应该在启动 Bootstrap 时进行适当的设置。
由于您正在进行BIOS
int
调用,因此应确保设置自己的堆栈。当BIOS跳转到物理内存地址0x00007C00
的代码时,您不能保证 SS/SP 指向足够的堆栈空间,甚至不能保证它有效。唯一的要求是BIOS在该位置开始执行您的代码,但它没有说明应该使用什么 CS 和 IP 来执行。BIOS还将通过DL
中的 Boot 驱动器。单个物理内存位置可以被许多不同的segment:offset对引用。例如,这些都指向 Boot 加载程序的物理地址:
字符串
正如你所看到的,上面的例子给予了你一个想法,有不止一种方法可以用segment:offset对来寻址一个内存位置。发帖者给出的代码假设 CS 段将是
0
。可以在代码中观察到org 7c00h
,这表示当编译器生成对象文件时,所有绝对近内存引用将偏移0x7C00
。由于我们将在内存中的0x7C00
处进行物理加载,因此我们的 DS 必须是0x000
。这与OP的代码有什么关系?请注意,我们从以下内容开始:
型
我们盲目地移动 CS 中的内容并将其转移到 DS 和 ES。我们的代码特别需要一个
0x0000
的 DS 才能正常工作(origin为0x7C00
)。我给出了一些Map到物理位置0x7C00
的 CS:IP 对的示例。如果BIOS跳到我们的代码,特别是 * 远跳 * 到0x0000:0x7C00
,我们的 CS 将是0x0000
,IP 将是0x7C00
。如果我们把0x0000
移到 DS 和 ES,一切都会很好。如果BIOS * 跳到 * 0x 07 C 0:0x 0000,会发生什么?我们的 CS 中有0x07C0
,IP 中有0x0000
。如果我们将 CS 移到 ES 和 DS,所有这些段都是0x07C0
,但我们编写的代码是相对于0x0000
的段的。如果使用错误的片段,会出现什么问题?假设
Bootmessage
被汇编程序放置在偏移量0x7C50
(0x 50 + 0x 7 C 00原点)处。现在执行以下代码:型
由于没有指定任何段,因此它将与
DS:BootMessage
相同。如果我们的 DS 段被设置为0x07C0
,Bootmessage
被设置为0x7C50
,那么我们正在访问物理地址(0x 07 C 0 <<4)+0x7C50 =0xF850
。现在应该很明显-如果 CS 不为0,我们正在从一个不存在字符串的内存地址加载 BootMessage。解决这个问题很简单。不要假设 CS 是我们所期望的。编写引导加载程序以使用我们想要的。我们打算将 DS 和 ES 设置为段
0x0000
:型
一些虚拟机和真实的硬件可以使用
0x07C0:0x0000
far jmp 到我们的引导加载程序,而另一些则使用0x0000:0x7C00
。如果你假设 CS 中的值是你想要的,那么你的代码可能在某些平台上工作,而不是其他平台。zbwhf8kr2#
在你的台词里:
字符串
我不相信可以像这里一样直接将地址移动到AX,因为在x86中没有可用的指令来查询AX寄存器本身的地址指针。
相反,为什么不直接将其移动到BX中,如下所示:
型
不知道这是不是已经试过了??