0

我试图弄清楚在 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);
}
4

1 回答 1

3

我试图弄清楚在 32 位保护模式下页面是如何翻转的。我运行 0x4F0A 并将输出表存储在 0x00008100。设置 LFB 位置的命令应该位于 0x00008102 是否正确?

0x00008102 处的 16 位值可能包含“设置/获取显示开始”功能的偏移量(在 VBE 的代码段中)。如果是这样,您需要在 GDT 中设置各种描述符(例如“VBE 的 32 位代码段”、“VBE 的数据段”)并使用 32 位远调用以“32- VBE 的位代码段”,同时在您使用所需的任何 VBE 加载 DS 和/或 ES 后,还使用(零扩展到 32 位)“0x00008102 处的值”加载 EIP。

然而; 对于 VBE 3.0(最新版本和最有可能适用于 20 岁以下计算机的 VBE 版本),该功能是可选的,可能不存在。反而; VBE 3.0 增加了“VBE 3.0 保护模式接口”(这是保护模式的 16 位代码,允许视频 ROM 回收现有代码,而不必担心微型 64 KiB ROM 中的空间不足)。

当然,对于非常旧的显卡(VBE 2.0 之前),“VBE 3.0 保护模式接口”永远不会存在。

这意味着要支持“所有 VBE”,您必须使用实模式、virtual8086 模式或 VBE 1.2 及更早版本的解释器;并且可以为 VBE 2.0 和 VBE 3.0 使用相同的“实模式、virtual8086 模式或解释器”(以避免处理“VBE 2.0 保护模式接口”和“VBE 3.0 保护模式接口”的额外麻烦)。

还有其他问题;主要是,VBE 不提供任何“垂直同步上的 IRQ”,如果您使用“垂直同步上设置显示开始”选项(在 VBE 的“设置/获取显示开始”功能中)会浪费大量 CPU 时间轮询检测是否/何时开始垂直同步,如果你不这样做,你最终会撕裂(避免撕裂是首先进行“翻页”的全部要点)。可以通过使用计时器来模拟“垂直同步上的 IRQ”(具体来说,在计时器到期时调用“设置/获取显示开始”,然后使用“设置/获取显示开始”返回到调整下一个计时器何时到期,以便您知道计时器将在垂直同步发生之前到期)。

另一件需要担心的是 VBE 代码中的错误。一般来说,经常使用的代码(例如设置视频模式)经过更多的测试并且不太可能出现错误,而很少使用的代码(例如设置显示开始)更有可能出现错误(并且崩溃,并破坏一切) . 我不确定,但我认为可以通过在“CPL=3 沙箱”(如进程)中隔离 VBE 的代码(通过“VBE 保护模式接口”执行)来减轻一些风险。

当然,对于现代计算机(使用 UEFI),VBE 本身根本不存在。并且 UEFI 没有提供任何替代方法来进行翻页。这意味着(如果您使用 VBE 和翻页)将很难将操作系统移植到以后仍然相关的硬件。

由于所有这些原因;最好使用“引导加载程序使用任何固件提供的帧缓冲区,内核/操作系统只使用帧缓冲区而不使用其他任何东西(直到/除非它启动本机视频驱动程序)”;并避免为(充其量)无法正常工作的事情做大量工作。

知道这是该命令的位置,我将如何在不返回实模式的情况下更改 C 中 LFB 的位置?

大多数 C 编译器不支持分段;这意味着您必须使用汇编语言存根来加载 VBE 的段(包括加载 VBE 代码段的“远调用”)并在之后恢复您的正常段。

您还需要担心如果在 VBE 的代码运行时发生 IRQ 会发生什么。你真的不想禁用 IRQ(因为不能保证 VBE 的功能会很快,也不能保证在 VBE 的代码运行时禁用 IRQ 不会破坏所有设备驱动程序的 IRQ 延迟,尤其是对于“浪费很多等待垂直同步时的 CPU 时间”情况);所以所有的中断处理程序都希望能够处理中断 VBE 的代码。

除此之外; 您可以将“显示开始”视为 LFB 中发送到监视器的第一个像素的偏移量(请注意,“显示开始”也可用于平滑滚动 - 例如,仅移动“显示开始”一行像素一次垂直滚动一个像素)。您还需要一些保护措施(例如,如果 LFB 不足以容纳 2 帧,则退回到“不翻页”,基于 VBE 的“返回”返回的结构的“TotalMemory(以 64 KiB 块)”字段Controller Information”以及垂直分辨率和“bytesPerLine”取自 VBE 的“Get Mode Information”返回的结构)。

于 2020-09-15T06:55:40.237 回答