在内核中写入像素值C++



我最近对编写一个简单的内核感兴趣。我在互联网上做了一些搜索,遇到了OSDev Wiki。我设置了基本内核(在经历了一些挫折之后,设置了交叉编译器)。现在我想更进一步:我想开始将值写入单个像素。我遇到的唯一令人满意和可以理解的答案是 Wiki 上的答案,在保护模式下绘图。我想使用提供的函数,但似乎仍然无法理解我需要传递什么作为参数。下面是我正在使用的函数的代码,我不明白我需要为第一个参数传递什么。我需要一些内存缓冲区(类似于用于文本的terminal_buffer)吗?

/* only valid for 800x600x32bpp */
static void putpixel(unsigned char* screen, int x,int y, int color) {
unsigned where = x*4 + y*3200;
screen[where] = color & 255;              // BLUE
screen[where + 1] = (color >> 8) & 255;   // GREEN
screen[where + 2] = (color >> 16) & 255;  // RED
}

这可能是一个愚蠢的问题,因为我对操作系统开发非常陌生。

提前感谢,

爪哇

顺便说一句:我正在做x86代码。我也看到了这个问题,并尝试在C++中内联它。此代码可以编译,但是如果我调用该函数,操作系统会拒绝启动。它只能到达此阶段:在返回 GRUB 菜单屏幕之前引导到的阶段。但是,如果我能找到替代解决方案,这可能无关紧要。这是替代选项:

void setPixel () {
asm ("mov %ah, 0x0C");
asm ("mov %al, 0x13");
asm ("int $0x10");
asm ("mov %ah, 0x0C");
asm ("mov %bh, 0");
asm ("mov %dx, 5");
asm ("mov %cx, 5");
asm ("mov %al, 0x04");
asm ("int $0x10");
}

我没有在保护模式下编码,但是如果我没记错的话,在保护模式下,中断的处理方式不同,需要一些桥接才能访问,因此第二个中断示例代码将不起作用(但我可能是错的)。尝试谷歌如何从保护模式访问VGA/VESA/VBE BIOS功能。

第一个示例假设系统中存在VESA/VBE卡,并配置为视频模式,800x600x32bpp从远指针屏幕开始的LFB模式下。我也从来没有做过这样的事情,但是当您设置VGA/VESA的视频模式时,默认情况下它会切换到页面模式。

因此,如果您只是切换到800x600x32bpp,那么您将获得页面模式(本机)。因此,VRAM在实模式下以0xA000:0000 - 0xA000:FFFF映射。当您处于保护模式时,您需要以某种方式将其转换/映射到 32 位空间。

此外,由于您获得了 32 位模式,您应该使用DWORD表示颜色并通过单个操作存储像素(例如stosd或具有DWORD *screen并且不使用地址计算where = x + y*800;中的4*)。

所以你有 2 个选择:

  1. LFB 线性帧缓冲器

    VESA/VBEgfx卡具有使用LFB的功能(我认为从1.2或2.0版本开始),这意味着您可以将VRAM线性映射到指定的内存空间。因此,在这种情况下,screen是您将VRAM映射到的地址。关于如何做到这一点,您应该查阅VESAVBE文档。如果没有正确的配置,您的示例将永远无法正常工作。

  2. 页面模式

    在页面模式下,您只能访问64 KByte的VRAM。 对于上面的视频模式320x200x8bpp这还不够,您需要选择要使用的 64KB 内存段。 这称为分页。看这里 #2 VGA GFX 模式也有真正的模式 VESA示例。这个想法是根据坐标计算地址和页面。在您的情况下(对于 BYTE 指针):

    BYTE far screen=(BYTE far*)0xA0000000;
    DWORD adr = 4*x + 4*800*y;
    DWORD page = adr>>16; adr &= 0xFFFF;
    VESApage(page);
    screen[adr]=r; adr++;
    screen[adr]=g; adr++;
    screen[adr]=b;
    

    或:

    DWORD far screen=(DWORD far*)0xA0000000;
    DWORD adr = x + 800*y;
    DWORD page = adr>>14; adr &= 0x3FFF;
    VESApage(page);
    screen[adr]=rgba;
    

    VESApage()来源在上面的链接中。因此,在这种情况下,screen是固定的VRAM地址,但正如我之前提到的,为了在保护模式下工作,这可能会发生很大变化。您还应该查看程序集 8086 中的图形模式

由于您提供的链接证实了我的怀疑,即您无法直接从保护模式访问 BIOS功能,因此我会选择LFB,因为它更快,并且在视频模式配置后不需要任何进一步的BIOS功能访问。因此,您必须在切换到保护模式之前设置视频模式!!.

希望参数color,x,y你很清楚。此外,如果您不知道BYTEDWORD是什么,它们unsigned ints 8 和 32 位宽。

相关内容

  • 没有找到相关文章

最新更新