32 位 C 内核 - 渲染到 VGA 时奇怪的连续重绘

32 bit C kernel - Weird continous redrawing when rendering to VGA

我在为我用 C 编写的内核设置任何类型的功能时遇到问题。我已经完成了在 Assembly 中编写我的引导加载程序的步骤,然后编译我的 C 内核并将其加载到内存中并运行它。

问题是,每当我尝试添加任何类型的 backbone 例如 VGA 图形 class 以轻松组织渲染到 VGA 内存的方法时,我的内核就会崩溃并且仿真刚开始不断重绘自身,我看不出与我试图渲染到 VGA 内存的内容有任何相似之处。

我已经尝试通过许多不同的方式设置主干,通过在线学习无数教程,我很乐意使用一种终端界面,如果它能开始工作的话。

我一直在将我的代码上传到 Bitbucket 存储库,其中包括我的 Makefile、程序集引导加载程序、程序集内核入口点和我所有的内核 C 源文件。我会保留它 public 并避免向其中提交任何内容,以便大家可以参考它,直到我找到我正在寻找的答案。

Here 是我的 "Operating System" 的 Bitbucket 存储库。

我在 Ubuntu 14.04 桌面 64 位上运行。如果您需要任何其他信息或资源来帮助您找到答案,请告诉我,我会进行编辑。

提前感谢您的帮助和考虑。

编辑:

显然,将我的代码组织到 Bitbucket 存储库中进行显示是不受欢迎的,因此我将尝试向您详细说明我正在做的事情可能会导致问题。

我的引导加载程序运行并将内核的 15 个扇区(15 * 512 字节)读入内存,尽管我的内核可能没有 15 个扇区的数据,但这似乎不会导致问题(除非它导致一个问题,我不知道)。我将我的内核加载到地址偏移量 0x0500 之后,我将我的堆栈(在跳入我的内核之前)初始化为位于地址偏移量 0x9FBFF。

之后,我跳转到我的内核(实际上,我跳转到我的汇编内核入口文件,它调用了 C 内核的主要函数)。

当我的内核开始运行时,它会尝试使用我制作的一些主干文件将文本图形绘制到 VGA 内存地址 0xB80000。我可以做简单的事情比如这行代码

unsigned char* vidmem = (unsigned char*) 0xB80000;
*vidmem = 'X';

它工作正常,我可以在我的模拟器的左上角看到一个 X 以及引导加载程序中尚未被覆盖的其他图形。

当我尝试做更复杂的事情时,问题开始出现,例如调用其他试图将文本图形绘制到屏幕上不同列和行的骨干源文件,存储最后打印的列和行到,处理滚动,打印整个字符串并考虑滚动和新行等。

我完全不明白为什么会发生这种情况,我对内存和汇编指令如何以可能导致问题的方式与计算机交互有中等到初级的理解。

再次强调,如能就此问题提供任何帮助,我们将不胜感激。

我看到的最明显的问题是您寻址 VGA 内存的逻辑不可靠。

您将指向视频内存的指针声明为 unsigned char *:

unsigned char* terminal_buffer;
...
static unsigned char* const VGA_MEMORY = (unsigned char*) 0xB8000;
...
terminal_buffer = VGA_MEMORY;

但是,您正试图将完整的 VGA 字符值写入每个位置,例如在 terminal_init():

  const unsigned int index = r * VGA_WIDTH + c;
  terminal_buffer[index] = make_vga_entry(' ', terminal_color);

您没有将索引乘以 2,因此最终会将 VGA 条目的低 8 位(在本例中为 0x20)写入 VGA 缓冲区中的每个内存位置。当您开始向终端写入文本时,这会导致奇怪的结果,因为每隔一个字节最终都会被解释为属性对而不是字符!

幸运的是,解决方案很简单:将 terminal_buffer 声明为 16 位元素的数组:

uint16_t *terminal_buffer = VGA_MEMORY;
^^^^^^^^

(P.S: 我建议看一下the OSDev article on VGA hardware。)