我试图用NASM绘制DOSBOX中VGA图形的屏幕。我的代码可以很好地写到一个黑色屏幕上,但是如果我编辑一个已经是特定颜色的像素,输出的颜色将是与我的新颜色相同的前一个颜色ORed。例如,如果我填充一个红色的屏幕,然后再填充它作为蓝色它最后的屏幕将不是蓝色,但它将是一个洋红色。
下面是我的代码,它应该填充屏幕蓝色,然后是绿色,而是填充屏幕蓝色,然后再用绿色替换蓝色内存,从而形成一个填充屏幕的屏幕。我在DOSBOX中看到了这种情况,减缓了cpu的速度。
org 100h
section .text
start:
mov ax, 4F02h
mov bx, 102h
int 10h ; enter 800x600 16 color VGA mode
push 0x01 ; blue
call fill_screen
push 0x2 ; green
call fill_screen
jmp $
fill_screen:
; multiply screen width by height then divide by 8 to get number of times to repeat write operation, push to stack
mov ax, [screen_width]
mov dx, [screen_height]
mul dx
mov cx, 8
div cx
push ax
; point es to video memory
mov ax, 0A000h
mov es, ax
pop cx ; times to repeat write operation
pop dx ; return address
pop ax ; color
push dx ; put return address back on stack
mov dx, 03c4h ; register selection port
shl ax, 8 ; color is one byte, it was in al but we need it in ah so shift left one byte
mov al, 02h ; map mask
out dx, ax ; write all the bitplanes
xor di, di ; video memory pointer to start
mov ax, 0ffh ; write to every pixel
rep stosb
ret
section .data
screen_width dw 320h
screen_height dw 258h
这里在第5节中说,您可以更改写模式以替换,或者,xor,或者通过写到端口03CFh。它们包括切换到XOR模式的示例代码:
mov ax,1803h
mov dx,03CEh
out dx,ax
当我在第6行(int 10h)之后添加它时,什么都不会发生,并且代码的输出仍然是teal的。由于蓝色或绿色与蓝色XOR绿色相同,所以我将绿色输入更改为洋红(请执行第9行push 0x5
)。输出现在是洋红色,这意味着内存仍然处于OR模式,而不是在XOR模式下。
下面是最后的测试代码:
org 100h
section .text
start:
mov ax, 4F02h
mov bx, 102h
int 10h ; enter 800x600 16 color VGA mode
; switch to XOR write mode (?)
mov ax, 1803h
mov dx, 03CEh
out dx, ax
push 0x01 ; blue
call fill_screen
push 0x5 ; magenta
call fill_screen
jmp $
fill_screen:
; multiply screen width by height then divide by 8 to get number of times to repeat write operation, push to stack
mov ax, [screen_width]
mov dx, [screen_height]
mul dx
mov cx, 8
div cx
push ax
; point es to video memory
mov ax, 0A000h
mov es, ax
pop cx ; times to repeat write operation
pop dx ; return address
pop ax ; color
push dx ; put return address back on stack
mov dx, 03c4h ; register selection port
shl ax, 8 ; color is one byte, it was in al but we need it in ah so shift left one byte
mov al, 02h ; map mask
out dx, ax ; write all the bitplanes
xor di, di ; video memory pointer to start
mov ax, 0ffh ; write to every pixel
rep stosb
ret
section .data
screen_width dw 320h
screen_height dw 258h
如何解决这个问题,从而进入不同的写入模式?是否有不同的更好的方式来写入视频内存,而不是使用我应该使用的写入模式?如何进入替换模式?
发布于 2022-07-14 14:22:19
关于VGA硬件的一些参考:硬件,https://web.stanford.edu/class/cs140/projects/pintos/specs/freevga/vga/vgamem.htm
首先,XOR模式(和其他模式)不使用已经存在于视频内存中的数据的XOR。它们使用锁存寄存器进行异或,这些寄存器在从视频存储器读取时加载。锁存寄存器保持其值,直到从视频内存中读取另一个值为止。如果您不从视频内存中读取,那么锁存寄存器有一个未定义的值。
要保持正常模式(NOP模式),只需将模式设置为0:
mov ax,0003h
mov dx,03CEh
out dx,ax
另外,当写入03c4h/reg 2时,您设置了一个掩码,它将应用于对视频内存的所有写入,过滤您所写的每一个位。将掩码设置为0Fh将允许按预期写入所有位。如果您不使用掩码值0Fh (这是您的情况,而是用您的颜色填充它),那么掩码的0位将从锁存寄存器中取出,因为您没有读取这些寄存器。
若要编写没有掩蔽的颜色,请将掩码设置为0Fh,并编写实际颜色而不是FFh:
mov dx,03C4h
mov ax,0F02h
out dx,ax
mov es:[di], <color> ; example write
如果希望对每个像素使用XOR和掩码操作,则需要在每次写入之前正确地填充闩锁,方法是执行虚拟读取:
mov bl, es:[di] ; ignore bl if not needed
mov es:[di], <color> ; example write with VGA operations
请注意,使用bl
并自己执行xor/掩码的替代方法并不复杂。
https://stackoverflow.com/questions/72984211
复制相似问题