我早就知道,通过使用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显卡的情况下运行代码的准确度。