我正在尝试弄清楚在32位保护模式下页面是如何翻转的。我运行0x4F0A并将输出表存储在0x00008100中。设置LFB位置的命令应该位于0x00008102,这对吗?知道这是该命令的位置,我如何在不返回实模式的情况下更改c中的LFB的位置呢?
void main() {
char vmem_back_buffer0[3932160];
char vmem_back_buffer1[3932160];
char* prot_mode_desc = (char*)0x00008102;
/* ... code to file those buffers with data is removed for brevity ... */
// Here I change the LFB location to vmem_back_buffer0
// Here I change the LFB location to vmem_back_buffer1
while (TRUE);
}发布于 2020-09-15 14:55:40
我正在尝试弄清楚在32位保护模式下页面是如何翻转的。我运行0x4F0A并将输出表存储在0x00008100。设置LFB位置的命令应该位于0x00008102,对吗?
0x00008102处的16位值可以包含"Set/Get Display Start“函数的偏移量(在VBE的代码段中)。如果是这样的话,你需要在你的GDT中设置不同的描述符(例如“VBE的32位代码段”,“VBE的数据段”),并使用一个32位的远调用来加载CS“VBE的32位代码段”,同时在你加载DS和/或ES需要的任何VBE之后,也用(零扩展到32位) "value at 0x00008102“加载EIP。
但是,对于VBE3.0(最新版本,也是最有可能的VBE版本,适用于不是20+年限的计算机),该功能是可选的,可能不存在。取而代之的是,VBE3.0增加了“VBE3.0保护模式接口”(这是保护模式的16位代码,允许视频只读存储器回收现有代码,更少地担心在微小的64 KiB只读存储器中空间不足)。
当然,对于非常旧的视频卡(在VBE 2.0之前),"VBE 3.0保护模式接口“将永远不会存在。
这意味着要支持“所有VBE”,你必须使用实模式、virtual8086模式或用于VBE1.2和更早版本的解释器;并且可以对VBE2.0和VBE3.0使用相同的“实模式、virtual8086模式或解释器”(以避免处理“VBE2.0保护模式接口”和“VBE3.0保护模式接口”的额外麻烦)。
还有其他问题;主要是,VBE没有提供任何“垂直同步的IRQ”,如果你使用“设置垂直同步的显示开始”选项(在VBE的"Set/Get Display Start“功能中),它将浪费大量的CPU时间轮询来检测是否/何时垂直同步已经开始,如果你不这样做,你将以撕裂结束(避免撕裂是做”翻页“的首要目的)。可以通过使用计时器来模拟“垂直同步时的IRQ”来解决这一问题(具体地说,当计时器到期时调用"Set/Get Display Start“,然后使用"Set/Get Display Start”返回的时间来调整计时器下一次到期的时间,这样您就知道计时器将在垂直同步发生之前到期)。
另一件要担心的事情是VBE的代码中的bug。通常,频繁使用的代码(例如,设置视频模式)测试较重,不太可能有错误,而很少使用的代码(例如,设置显示开始)更有可能有错误(并崩溃,并破坏一切)。我不确定,但我认为可以通过隔离VBE的代码(通过.或者是"CPL=3沙箱“内的"VBE保护模式接口”(就像一个进程)。
当然,对于现代计算机(使用UEFI),VBE本身根本不存在;并且UEFI不提供任何可选的翻页方法。这意味着(如果你使用VBE和翻页)很难将操作系统移植到以后仍然相关的硬件上。
由于所有这些原因,最好使用“引导加载程序使用任何固件设置帧缓冲区,内核/OS只使用帧缓冲区而不使用其他(直到/除非它启动本机视频驱动程序/s)”;并避免为(充其量)不能很好地工作的事情做大量的工作。
如果知道这是该命令的位置,我该如何在不返回实模式的情况下更改c中
的位置呢?
大多数C编译器不支持分段;这意味着你必须使用汇编语言存根来加载VBE的代码段(包括加载VBE的代码段的“远调用”),然后恢复正常的代码段。
您还需要考虑如果在VBE的代码运行时发生IRQ会发生什么。你真的不想禁用IRQ (因为不能保证VBE的功能会很快,也不能保证在VBE的代码运行时禁用IRQ不会破坏所有设备驱动程序的IRQ延迟,特别是在“等待垂直同步时浪费大量CPU时间”的情况下);所以所有的中断处理程序都希望能够处理中断VBE的代码。
除此之外,您可以将“显示开始”视为LFB中发送到监视器的第一个像素的偏移量(请注意,“显示开始”也可用于平滑滚动-例如,移动“显示开始”一行像素,以便一次垂直滚动一个像素)。你还需要一些保护措施(例如,如果LFB不够大到2帧,基于VBE的"Return Controller Information“返回的结构的"TotalMemory (in 64 KiB chunks)”字段,以及从VBE的"Get Mode Information“返回的结构中获取的垂直分辨率和"bytesPerLine”),则返回到“无翻页”。
https://stackoverflow.com/questions/63893771
复制相似问题