这段代码如何显示到屏幕上?

How does this code to display to screen works?

当我找到真正的 OS 开发教程时,我正在浏览整个 Internet 上的内核开发教程。

我查看了代码,但我无法理解这一点。

代码如下:

int main(void){

char *str = "Hello, world", *ch;

unsigned short *vidmem = (unsigned short*) 0xb8000;
unsigned i;

for (ch = str, i = 0; *ch; ch++, i++)
    vidmem[i] = (unsigned char) *ch | 0x0700;

for (;;);
}

当我使用 Dev C++ 编译上述代码并生成 Win32 控制台或 Windows 应用程序时,当我 运行 它时它崩溃了,它告诉我我的程序 "has stopped working" 和终止。它似乎在循环中的这一行失败:

vidmem[i] = (unsigned char) *ch | 0x0700;

代码有什么问题,我该如何解决?

在for循环中:

for (ch = str, i = 0; *ch; ch++, i++)
    vidmem[i] = (unsigned char) *ch | 0x0700;

条件部分 *ch 指示 C 编译器在表达式为 true(非零)时继续循环.只要 *ch 不是 NUL(\0) 终止符,表达式就会 true 并继续循环。当它到达一个为零的字符时,条件表达式将为 false 并且循环退出。它有效地循环遍历一个字符串,直到它到达 NUL 终止字符。

vidmem[i] = (unsigned char) *ch | 0x0700; 崩溃的原因是因为 vidmem 被赋予了显存地址 0xb8000。基于 Win32 的应用程序无法访问此内存,OS (Windows) 将使您的应用程序出错并显示有关程序不再工作的错误消息。

解决这个问题的唯一方法是以可以用作 MS-DOS 程序的方式编译它:

  • 使用 16 位 C 编译器和 运行 在 MS-DOS 或像 DosBox
  • 这样的 MS-DOS 模拟器中编译
  • 将其编译到您的内核中并在裸机环境(QEMU、Virtualbox、VMWare 等)中进行测试

*ch | 0x0700 获取当前字符并将其按位或运算为 0x0700。这有效地创建了一个 16 位字,字符在低 8 位,0x07 在高 8 位。

这样做是因为您在使用内存区域 0xb8000 的标准彩色文本视频模式中看到的每个字符都由 2 个字节(一个 16 位字)组成。这在 Wikipedia article:

中描述

如果循环中正在处理的当前字符是字母 H (0x48) 那么 *ch | 0x0700 将变为 0x0748 然后存储在特定的内存位置视频显示。

您可能希望阅读 C 中的位操作。我发现这个 tutorial 可能有帮助。