【问题标题】:Using 16 bit mode to print a letter WITHOUT bios routines使用 16 位模式打印没有 bios 例程的字母
【发布时间】:2025-12-13 05:05:01
【问题描述】:

我意识到在保护模式下,可以通过修改内存位置 0xb8000 等来使用内存映射 I/O 来打印字母...... 我们可以在 16 位实模式下做到这一点吗? (使用分段访问位置,然后进行修改)

这是我的汇编代码...

[bits 16]
mov ax,0xb800
mov ds,ax    #This is the segment register that should hopefully give me 0xb8000
mov byte[ds:0x0000],'X'
mov byte[ds:0x0001],0x0f

times 510-($ -$$) db 0
dw 0xaa55

顺便说一句,这不起作用..

[编辑] 结果我最后需要 jmp $ 来防止任何随机代码执行并且代码按预期工作

【问题讨论】:

  • 这只是好奇
  • 是的,这样的东西应该可以在引导加载程序中使用。 (顺便说一句,它不完全是 MMIO;您正在写入设备内存,而不是写入每次读取或写入都有副作用的 IO 寄存器)。您是否尝试遵循写入 VGA 内存的工作示例? VGA 和 bootloader 标签中应该还有其他的;使用 SO 的搜索。另外,“不工作”怎么办?在 BOCHS 调试器中单步执行会发生什么? IDK 如果您在代码之后没有包含 hlt / jmp 循环很重要,那么它会继续以 add [mem], al 执行 00 00 字节(使用一些寻址模式,IDK 16 位 modrm)
  • 你可能想在那段代码之后放置一个jmp $无限循环,我不知道00aa55的操作但它甚至有可能会在引导扇区的末尾运行并执行任意代码 - 这不太可能结束。
  • 而且,是的,这实际上是当时为提高速度而采取的方式,只是后来才出现可移植性问题。粗略一瞥,依靠可能受损的记忆而不是研究:-),你所拥有的应该可以正常工作。请记住,地址是用于 CGA 的,我相信 MDA 和 EGA 使用完全不同的地址。由于您的问题上有一个 VGA 标签,您可能需要先进行一些初始化,VGA 具有决定模式及其在地址空间中的位置的寄存器。
  • 您可能还想看看我们的复古计算姊妹网站retrocomputing.stackexchange.com。他们可能在该主题上更多知识渊博。

标签: assembly x86-16 bootloader osdev vga


【解决方案1】:

它应该可以工作,有两个可能的失败原因:

  • 如果您尚未处于文本模式,则 B800 段不用于在屏幕上呈现文本。 (很可能使用现代 BIOS)
  • 如果您有单色屏幕,您的显卡可能会决定使用 B000 而不是 B800。 (现代 BIOS 不太可能)。

【讨论】:

    【解决方案2】:

    原来我只需要最后的 jmp $ 来防止任何随机代码执行。代码按预期工作

    【讨论】: