首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在VGA模式下写入图形内存的写入模式不发生变化?

为什么在VGA模式下写入图形内存的写入模式不发生变化?
EN

Stack Overflow用户
提问于 2022-07-14 17:02:34
回答 1查看 77关注 0票数 0

我试图用NASM绘制DOSBOX中VGA图形的屏幕。我的代码可以很好地写到一个黑色屏幕上,但是如果我编辑一个已经是特定颜色的像素,输出的颜色将是与我的新颜色相同的前一个颜色ORed。例如,如果我填充一个红色的屏幕,然后再填充它作为蓝色它最后的屏幕将不是蓝色,但它将是一个洋红色。

下面是我的代码,它应该填充屏幕蓝色,然后是绿色,而是填充屏幕蓝色,然后再用绿色替换蓝色内存,从而形成一个填充屏幕的屏幕。我在DOSBOX中看到了这种情况,减缓了cpu的速度。

代码语言:javascript
运行
复制
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模式的示例代码:

代码语言:javascript
运行
复制
mov ax,1803h
mov dx,03CEh
out dx,ax

当我在第6行(int 10h)之后添加它时,什么都不会发生,并且代码的输出仍然是teal的。由于蓝色或绿色与蓝色XOR绿色相同,所以我将绿色输入更改为洋红(请执行第9行push 0x5)。输出现在是洋红色,这意味着内存仍然处于OR模式,而不是在XOR模式下。

下面是最后的测试代码:

代码语言:javascript
运行
复制
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

如何解决这个问题,从而进入不同的写入模式?是否有不同的更好的方式来写入视频内存,而不是使用我应该使用的写入模式?如何进入替换模式?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-14 22:22:19

关于VGA硬件的一些参考:硬件https://web.stanford.edu/class/cs140/projects/pintos/specs/freevga/vga/vgamem.htm

首先,XOR模式(和其他模式)不使用已经存在于视频内存中的数据的XOR。它们使用锁存寄存器进行异或,这些寄存器在从视频存储器读取时加载。锁存寄存器保持其值,直到从视频内存中读取另一个值为止。如果您不从视频内存中读取,那么锁存寄存器有一个未定义的值。

要保持正常模式(NOP模式),只需将模式设置为0:

代码语言:javascript
运行
复制
mov ax,0003h
mov dx,03CEh
out dx,ax

另外,当写入03c4h/reg 2时,您设置了一个掩码,它将应用于对视频内存的所有写入,过滤您所写的每一个位。将掩码设置为0Fh将允许按预期写入所有位。如果您不使用掩码值0Fh (这是您的情况,而是用您的颜色填充它),那么掩码的0位将从锁存寄存器中取出,因为您没有读取这些寄存器。

若要编写没有掩蔽的颜色,请将掩码设置为0Fh,并编写实际颜色而不是FFh:

代码语言:javascript
运行
复制
mov dx,03C4h
mov ax,0F02h
out dx,ax
mov es:[di], <color> ; example write

如果希望对每个像素使用XOR和掩码操作,则需要在每次写入之前正确地填充闩锁,方法是执行虚拟读取:

代码语言:javascript
运行
复制
mov bl, es:[di] ; ignore bl if not needed
mov es:[di], <color> ; example write with VGA operations

请注意,使用bl并自己执行xor/掩码的替代方法并不复杂。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72984211

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档