在32位x86汇编语言中(视频模式13h),清除屏幕的最佳方法是什么?

5

目前,我正在将屏幕缓冲区(screenbuffer db 64000 DUP(0))复制到视频内存中(从0a0000h开始),以清除屏幕。但我在想,重新设置视频模式是否更好,像这样:

mov ax, 13h
int 10h

似乎还有一种清屏的更好方法吗?

或者说清屏的方式是这样的吗?


2
你是否考虑过使用 REP STOSD 来完成它? - Michael Petch
2
顺便提一下,BIOS 调用速度相当慢。因此,如果您通过某种快速方式(例如 rep movsd)复制屏幕缓冲区,则您的方法实际上非常好。rep stosd 更快,但是如果您在每帧屏幕上绘制某些内容,则应在屏幕缓冲区上使用 rep stosd,然后在那里绘制,然后将其复制到屏幕上。与直接 VRAM 访问相比,int 10h 解决方案较差(即使您像访问不幸模式中的 VRAM 这样受罚)。如果您绘制足够多的东西以覆盖整个屏幕缓冲区,则无需清除它(例如 DOOM1/2 没有清除)。 - Ped7g
2个回答

4

有一个INT 10H函数可以清除屏幕:AH=06h, AL=00h

你可以在BH中设置颜色。

这是一个向上滚动窗口INT 10H函数,如果AL=0,则清除屏幕。

该函数适用于在其他寄存器中设置的矩形区域,例如DH =较低行号,DL =右列号。

清除屏幕的标准方法是将CX设置为0000H,DL设置为0040:[004a]-1(通常为79),DH设置为0040:[0084](通常为24),BH设置为07H(白底黑字视频属性),并将AL设置为00H(以清除整个屏幕)。


这似乎只有在将DL设置为最小值39和DH设置为最小值24时才能正常工作。我猜这与屏幕的宽度和高度有关,但我不明白为什么是39和24。 - T Snake
1
函数还接受应用的字符窗口矩形,我已经扩展了答案。 - Fedor Losev

4
你可以使用STOSD加上REP前缀来清除视频模式 13 (320x200x256色)的视频内存。 REP STOSD将重复STOSD计数存储在ECX中。 STOSD会将EAX中的每个DWORD写入到ES:[EDI]中,每次增加4个EDI。

REP:重复字符串操作计数寄存器中指定的次数。

STOSD:将EAX寄存器中的双字存储到目标操作数中。

示例代码可能如下:

cld                    ; Set forward direction for STOSD
mov ax, 0x0013
int 0x10               ; Set video mode 0x13 (320x200x256 colors)

push es                ; Save ES if you want to restore it after
mov ax, 0xa000
mov es, ax             ; Beginning of VGA memory in segment 0xA000
mov eax, 0x76767676    ; Set the color to clear with 0x76 (green?) 0x00=black
xor edi, edi           ; Destination address set to 0
mov ecx, (320*200)/4   ; We are doing 4 bytes at a time so count = (320*200)/4 DWORDS
rep stosd              ; Clear video memory
pop es                 ; Restore ES

这段代码假设你使用的是32位处理器,但不假设你正在运行非虚拟模式
如果使用16位处理器(8086/80186/80286),则必须使用16位寄存器,并使用REP STOSWCX将被设置为(320*200)/2而不是(320*200)/4。16位处理器不允许使用32位操作数,因此不支持STOSD
你可以轻松地将此代码转换为汇编语言函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接