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

时间:2018-03-09 19:59:31

标签: c++ graphics kernel drawing pixel

我最近对编写一个简单的内核感兴趣。我在互联网上进行了一些搜索并遇到了OSDev Wiki。我设置了基本的内核(经过一些挫折,交叉编译器)。现在我想更进一步:我想开始为单个像素写入值。我遇到的唯一令人满意和可理解的答案是Wiki上的那个,Drawing in Protected Mode。我想使用提供的功能,但仍然无法理解我需要传递的参数作为参数。下面是我正在使用的函数的代码,我无法理解第一个参数需要传递的内容。我需要一些内存缓冲区(类似于用于文本的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
}

这可能是一个愚蠢的问题,因为我对OS开发很新。

提前致谢,

的javax

顺便说一句:我正在做x86代码。我还看到了this问题,并尝试用C ++编写它。此代码编译,但如果我调用该函数,则OS拒绝启动。在返回GRUB菜单屏幕​​之前,它只进入此阶段:the stage it boots to。但是,如果我能找到替代解决方案,这可能就不足为重了。这是另一种选择:

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");
}

1 个答案:

答案 0 :(得分:0)

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

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

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

另外,当您使用32位模式时,您应该使用DWORD颜色并使用单个操作存储像素(例如stosdDWORD *screen并且不使用4*来自地址计算where = x + y*800;)。

所以你有两个选择:

  1. LFB线性帧缓冲区

    VESA / VBE gfx卡可以使用 LFB (我认为从版本1.2或2.0),这意味着您可以映射 VRAM 以线性方式指定内存空间。因此,在这种情况下,screen是您将 VRAM 映射到的地址。关于如何操作,您应该参考 VESA VBE 文档。如果没有正确配置,您的示例将永远不会有效。

  2. 页面模式

    在页面模式下,您只能访问 VRAM 64 KByte。对于320x200x8bpp以上的视频模式,这还不够,您需要选择要使用的64 KB内存段。这叫做分页。看这里#2 VGA GFX mode还有实模式 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地址,但正如我之前提到的,为了在保护模式下工作,这可能会发生很大变化。您还应该查看Graphics mode in assembly 8086

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

    希望参数color,x,y对您来说很清楚。如果你不知道BYTEDWORD是什么,它们是unsigned int的8和32位宽。