2

我早就知道,通过使用 CRTC 将行高更改为两个像素,可以在 IBM CGA 上实现伪 160 x 100 图形模式。几天来,我一直在尝试完成此操作,但走到了死胡同。

Intel® Open Source HD Graphics and Intel Iris™ Graphics Programmer's Reference Manual声称我可以在第 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

我对像这样的低级东西还不是很有信心,任何帮助都将不胜感激。

4

1 回答 1

8

您不是写信给地址 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 视频卡下运行代码的准确度。

于 2016-09-05T22:11:47.307 回答