在x86汇编中实现160x100模式

时间:2016-09-05 21:12:07

标签: assembly x86 intel dosbox undocumented-behavior

我已经知道有一段时间可以通过使用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

我对这样的低级别的东西还不是很有信心,任何帮助都会受到赞赏。

1 个答案:

答案 0 :(得分:6)

你没有写信给地址3b5h,你正在写地址3b50h。如果你想写地址3b5h,你需要加载ES为0,然后执行类似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控制器索引寄存器来进行选择。这意味着您的代码需要如下所示:

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视频卡时运行代码的准确程度。