Assembly 在x86汇编中实现160x100模式

Assembly 在x86汇编中实现160x100模式,assembly,x86,intel,dosbox,undocumented-behavior,Assembly,X86,Intel,Dosbox,Undocumented Behavior,我已经知道,通过使用CRTC将线高度更改为两个像素,可以在IBMCGA上实现伪160×100图形模式。几天来,我一直在努力实现这一目标,但却走到了死胡同 我可以在第45页(或PDF中的第59页)通过写入最大扫描线寄存器来实现这一点,或者这就是我从中的解释 我尝试过直接写入内存地址3B5,其值为0000000 1b,或者我认为是2条扫描线的代码。当我在DOSBox中测试它时,它一点作用也没有 如果您想查看我编写的将在NASM中汇编的代码: BITS 16 xor bx,bx mov ax, 3b5

我已经知道,通过使用CRTC将线高度更改为两个像素,可以在IBMCGA上实现伪160×100图形模式。几天来,我一直在努力实现这一目标,但却走到了死胡同

我可以在第45页(或PDF中的第59页)通过写入最大扫描线寄存器来实现这一点,或者这就是我从中的解释

我尝试过直接写入内存地址3B5,其值为0000000 1b,或者我认为是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,你可以在ES中加载0,然后执行类似于
mov BYTE[ES:3b5h],01的操作,但你也不想这样做。您链接的手册中给出的地址3b5h是一个“I/O地址”,这意味着它位于一个完全不同的地址空间中,您需要使用专门的输入和输出指令来访问该地址空间

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

mov dx, 3b5h
mov al, 01
out dx, al
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
请注意,这是您在这里可以使用的唯一形式。必须使用DX寄存器指定地址,使用AL寄存器提供要写入该I/O地址的数据

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

mov dx, 3b5h
mov al, 01
out dx, al
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视频卡的准确程度。

您是否在DOSBOX中配置了CGA图形适配器?DOSBOX是一个模拟器/虚拟机。在其内部运行的代码将看到整个机器,但其行为完全由DOSBox软件决定,而不是由DOSBox运行的主机的硬件决定。《英特尔手册》可能是有关VGA/CGA的有用文档来源,但请记住,它所记录的任何英特尔特定功能或行为都不会出现在DOSBox中。如果要编程实际的英特尔硬件,可以在裸硬件上启动代码。另请参阅以获取大量x86链接(无直接相关)。获得伪160x100图形模式的更简单方法可能是使用标准80x50 VGA文本模式和带有2x2块字符的自定义字体。另一种选择是使用VGA的320x200图形模式,在绘制像素时只需将像素的宽度和高度增加一倍。我想让它在DOSBox中工作,因为DOSBox当前配置为在CGA中运行。因为我没有访问实际硬件的权限,所以我求助于模拟器。您的代码似乎组装得很好,并且工作正常。谢谢@冲突检测:当答案解决您的问题时,您应该单击向上/向下投票箭头下的复选框,而不是留下感谢评论。这是我的第一个SO问题,假设我仍然了解问题的症结所在。