尝试填满屏幕时 VESA 跳过视频内存 "blocks"
VESA skipping "blocks" of video memory when trying to fill the screen
我正在开发一个简单的 OS' 内核,我正在尝试制作一个可以工作的视频库,以便以后使用。 (VBE 版本 3.0, 1920 * 1080px, 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);
}
}
这是我到目前为止得到的结果:
(我什至尝试用 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 位 ignored/masked 变为零(以帮助模拟只有 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 .
我正在开发一个简单的 OS' 内核,我正在尝试制作一个可以工作的视频库,以便以后使用。 (VBE 版本 3.0, 1920 * 1080px, 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);
}
}
这是我到目前为止得到的结果:
(我什至尝试用 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 位 ignored/masked 变为零(以帮助模拟只有 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 .