我早就知道,通过使用 CRTC 将行高更改为两个像素,可以在 IBM CGA 上实现伪 160 x 100 图形模式。几天来,我一直在努力实现这一目标,但走到了死胡同。
Intel® Open Source HD Graphics and Intel Iris™ Graphics Programmer's Reference Manual声称我可以在第 45 页(或 PDF 中的第 59 页)通过写入最大扫描线寄存器来执行此操作,或者这就是我从中解释的内容。
我已经尝试过直接写入值为 00000001b 的内存地址 3B5,或者我相信是 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 instruction 的唯一形式你可以在这里使用。您必须使用 DX 寄存器指定地址,并使用 AL 寄存器提供要写入该 I/O 地址的数据。
但那也不对。正如您链接的手册所解释的那样,I/O 地址 3b5h 是 MDA 数据端口,CGA 数据端口位于 I/O 地址 3d5h。最后,“最大扫描线寄存器”并不是唯一通过 I/O 地址 3d5h 访问的寄存器。有几个不同的寄存器使用这个地址。要选择要写入的寄存器,首先需要通过将其索引值写入 I/O 地址 3d4h 处的 CGA CRT Controller 索引寄存器来选择它。这意味着您的代码需要如下所示:
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 视频卡的准确程度。
关于assembly - 在 x86 汇编中实现 160x100 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39337743/