assembly - 如何使用汇编中的页面(TASM)?

标签 assembly graphics x86-16 tasm dosbox

我想创建一个类似Guitar Hero in Assembly(TASM)的游戏,我想我需要使用页面向上滚动屏幕。如何在上面的页面上打印矩形并向上滚动页面?

最佳答案

实际上,取决于视频硬件可用的内存量,不同的视频模式具有不同数量的可用“页面”。您可以看到一个几乎完整的列表here。但是,并非所有视频模式都支持多页。例如,mode 13h是VGA上的一种通用图形模式(之所以流行,是因为它允许直接操作视频内存的简化方法,从而使编程更加容易),仅支持一页,这意味着不可能以正常方式翻转页面。*您需要选择支持多页的模式。我自己不是图形模式的人,我不知道哪个受欢迎,推荐哪个。也许是0Dh,分辨率为320×200,具有16种颜色和8页?

在页面之间切换的标准方法是使用BIOS服务10h(视频功能),功能05h。这将选择 Activity 的显示页面。如在线文档here中所见,您将AH寄存器设置为功能标识符(05h),将AL设置为要选择的显示页面,然后调用中断10h:

mov  al, 01h   ; select display page 1
mov  ah, 05h   ; function 05h: select active display page
int  10h

或者,为了获得最佳性能,真正的汇编程序员将同时设置这两个AX寄存器,如下所示:
mov  ax, 0501h  ; AL == display page, AH == function 05h
int  10h

如果所请求的页面不存在,则中断调用将无效。您可以通过使用function 0Fh之后检查当前显示页码来验证这一点,它会返回BH寄存器中的 Activity 显示页:
mov  ax, 0F00h   ; AH == function 0Fh
int  10h

这就是您使用页面的方式,但实际上与滚动无关。您一次不能在屏幕上显示多个页面。出于滚动目的,您真正想要的是function 06h—scroll window up。 DX寄存器包含要滚动的矩形的左上角的坐标(DL ==列,DH ==行),而CX寄存器包含右下角的坐标(CL ==列,CH ==行)。 AL寄存器包含要滚动的行数,而BH寄存器包含将在新清除的区域中使用的screen attributes(颜色)。

例如,如果您想将由(0,0)×(80,20)定义的屏幕的矩形区域向上滚动10行,则可以执行以下操作:
xor  dx, dx     ; DL ==  0, DH ==  0
mov  cx, 1450h  ; CL == 80, CH == 20
mov  ax, 060Ah  ; AL == 10, AH == 06h
mov  bh, 0Eh    ; yellow foreground, black background
int  10h

此功能最常见的用途是清除整个屏幕。您可能会想到,这是通过将DX和CX设置为定义整个屏幕的坐标,然后将AL设置为0来使整个矩形变为空白来完成的。然后将清除屏幕,并用BH中指定的颜色属性填充。请记住,屏幕的原点(左上角)位于(0,0)。范围(右下角)取决于您所处的模式。

有一个补充功能07h,它向下而不是向上滚动窗口。否则,它的功能与功能06h完全相同。

请注意,就像我之前说的那样,正如链接文档中所述,这些滚动屏功能仅在当前 Activity 的显示页面上起作用。因此,向上或向下滚动屏幕后,几乎暴露的区域将被您指定的颜色/视频属性填充,然后您需要在其中绘制新的图形。

唯一的缺点是,当您将新内容绘制到屏幕上时,您可能会遇到闪烁。页面翻转将有助于防止这种情况的发生,但是要实现它还需要进行大量工作。您将无法通过自动滚动屏幕的一部分来帮助BIOS。您必须维护两个页面-一个页面包含当前正在屏幕上显示的内容,另一个页面已被绘制为好像已经滚动了一样。然后,您将直接从当前页面切换到新页面。

*实际上,您可以在模式13h中模拟页面翻转,但是,通过使用多个段,可以利用此模式允许的对视频内存的快速写入。基本上,您有一个段寄存器用于寻址实际的视频存储器,然后您有一个或多个其他段寄存器用于寻址“暂存”存储区,就好像它们是视频存储器一样。然后,当您要翻页时,只需将所有数据从暂存区域之一转移到实际的视频内存中即可。如果您熟悉现代的图形编程技术,那只是双重缓冲-绘制到屏幕外的缓冲区中,然后在准备就绪时将数据从该屏幕外的缓冲区复制到屏幕上。旧的一切又都是新的。

关于assembly - 如何使用汇编中的页面(TASM)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43487546/

相关文章:

c - 在外部汇编程序中修改 C 数组

gcc - GNU 汇编宏

c - 使用程序集中的 getchar 获取()函数

graphics - "Unlimited Detail"图形技术是如何工作的?

assembly - 从引导加载程序运行时 STOSB 指令不存储字节

audio - 使用 IBM-PC 扬声器播放音乐

assembly - 微软ASM面试有疑问吗?

java - bluebird 上的 JFrame 太小 (MAC)

r - 在 ggplot2 和其他 R 图形中创建新的形状调色板

assembly - 将 8086 上的 %EAX 寄存器清零