VESA 在尝试填满屏幕时跳过视频内存的“块” 编辑:

问题描述

我正在开发一个简单的操作系统内核,我正在尝试制作一个有效的视频库,以便我以后可以使用它。 (VBE 3.0 版,1920 * 1080 像素,32bpp)。
我用 C 编写了一个像素绘图函数,它似乎工作正常:

void putPixelRGB(struct MODEINFOBLOCK mib,short x,short y,int color) {
   int *pos = (char *)mib.framebuffer + x * 4 + y * 7680;
       *pos = color;
}

然后我尝试使用这个函数和两个 for 循环来填满整个屏幕:

for(int i = 0; i < 1920; i++) {
   for(int j = 0; j < 1080; j++) {
      putPixelRGB(mib,i,j,0xFFFFFF);
   }
}

这是我目前得到的结果:

enter image description here




(我什至尝试用 0xFF 填充视频内存中的每个字节,以确保我不会改变其他像素或内容:P...而且,呃...我得到了相同的结果。)
dloop:
   mov byte[eax],0xFF           ;eax contains the address of the FB memory.
   inc eax
   cmp eax,829440               ;829440 = 1920 * 1080 * 4
   jg done
   jmp dloop

done:
   hlt

知道为什么这不起作用吗?我是否以错误的方式访问内存?


编辑:

MODEINFOBLOCK 结构:

struct MODEINFOBLOCK {
    int attributes;
    char windowA,windowB;
    int granularity;
    int windowSize;
    int segmentA,segmentB;
    long winFuncPtr;
    int pitch;      

    int resolutionX,resolutionY;
    char wChar,yChar,planes,bpp,banks;
    char memoryModel,bankSize,imagePages;
    char reserved0;

    char readMask,redPosition;           
    char greenMask,greenPosition; 
    char blueMask,bluePosition;
    char reservedMask,reservedPosition;
    char directColorAttributes;

    char* framebuffer;                     
    long offScreenMemOff;
    int offScreenMemSize;
    char  reserved1 [206];
};

解决方法

您可能没有启用 A20 门。

在禁用 A20 门的情况下,物理地址的第 21 位被忽略/屏蔽为零(以帮助模拟只有 20 个地址线的旧 8086 CPU)。结果是当你尝试填充帧缓冲区时;第一个 1 MiB 像素有效,然后第二个 1 MiB 像素覆盖前 1 MiB 像素(留下未填充的黑色带),然后第三个 1 MiB 像素有效但被第四个 1 MiB 像素覆盖,并且以此类推。

这会创建“填充和未填充”水平带。如果您进行数学计算,(“1 MiB / 1920 / 4”)您会期望水平带的高度约为 136.5 像素;所以会有略多于 7 个频段(“1000 / 136.5”);这就是你得到的。

启用A20门;见https://wiki.osdev.org/A20_Line