[英]Why wont the write mode change for writing to graphics memory in VGA mode?
我正在嘗試使用 NASM 在 DOSBOX 中的 VGA 圖形中繪制屏幕。 我的代碼能夠完美地寫入黑屏,但是如果我編輯一個已經是某種顏色的像素,輸出顏色最終會是以前的顏色與我的新顏色相或。 例如,如果我填充紅色屏幕,然后再次將其填充為藍色,則最終屏幕將不是藍色,而是洋紅色。
這是我的代碼,它應該先填充屏幕藍色然后再填充綠色,而是填充屏幕藍色然后將藍色內存與綠色進行 OR 運算,從而產生青色填充屏幕。 通過降低 CPU 速度,我能夠在 DOSBOX 中看到這種情況。
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 節中,它說您可以通過寫入端口 03CFh 將寫入模式更改為替換、或、異或或和。 它們包括切換到 XOR 模式的示例代碼:
mov ax,1803h
mov dx,03CEh
out dx,ax
當我在第 6 行(int 10h)之后添加它時,什么也沒有發生,代碼的輸出仍然是青色。 由於藍色 OR 綠色與藍色 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
我該如何解決這個問題,以便我進入不同的寫入模式? 有沒有更好的方法來寫入視頻內存,放棄我應該使用的寫入模式? 我將如何進入替換模式?
關於 VGA 硬件的一些參考: https ://wiki.osdev.org/VGA_Hardware , 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/mask 的替代方法並不復雜。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.