在x86汇编中实现160x100模式



我早就知道,通过使用CRTC将行高度更改为两个像素,可以在IBM CGA上实现伪160 × 100图形模式。这几天我一直在努力完成这件事,但一直走到死胡同。

英特尔®开源高清图形和英特尔Iris™图形程序员参考手册声称我可以在第45页(或PDF中的第59页)通过写入最大扫描线寄存器来做到这一点,或者这就是我从中解释的。

我已经尝试直接写入内存地址3B5与00000001b的值,或2扫描线的代码,我相信。当我在DOSBox中测试它时,它没有任何作用。

如果您想查看我编写的将在NASM中组装的代码:

BITS 16
xor bx,bx
mov ax, 3b5h
mov es, ax
mov ah, 00000001b
mov BYTE [es:bx], ah    ; write 00000001b to 0x03b5:0000, right?
cli
hlt

我对这种低级别的东西还不是很有信心,任何帮助都会很感激。

你写的不是地址3b5h,你写的地址3b50h。如果你想写地址3b5h,你可以用0加载ES,然后做mov BYTE [es:3b5h], 01,但这也不是你想做的。您所链接的手册中给出的地址3b5h是一个"I/O地址",这意味着它位于一个完全不同的地址空间中,您需要使用专门的in和OUT指令来访问。

要将值01写入I/O地址3b5h,可以使用如下代码:

mov dx, 3b5h
mov al, 01
out dx, al

注意,这是您在这里可以使用的OUT指令的唯一形式。您必须使用DX寄存器指定地址,并使用AL寄存器提供写入该I/O地址的数据。

但这也不对。正如你所链接的手册所解释的,I/O地址3b5h是MDA数据端口,CGA数据端口在I/O地址3d5h。最后,"最大扫描线寄存器"不是通过I/O地址3d5h访问的唯一寄存器。有几个不同的寄存器使用这个地址。要选择要写入的寄存器,首先需要通过将其索引值写入I/O地址3d4h的CGA CRT控制器索引寄存器来选择它。这意味着您的代码需要看起来像这样:

mov dx, 3d4h   ; CGA CRTC Index Register
mov al, 09h    ; Maximum Scan Line Reigster
out dx, al
mov dx, 3d5h   ; CGA CRTC Data Port
mov al, 01     ; 2 scan lines
out dx, al

请注意,这仍然可能不正确,因为VGA将其他参数添加到最大扫描线寄存器。您可能需要保留这些值,但在实际的CGA硬件上这是不可能的,因为寄存器是只读的。这可能取决于您在模拟真实CGA显卡的情况下运行代码的准确度。

相关内容

  • 没有找到相关文章

最新更新