You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MASM下VGA 12h模式(640*480 16色)显存绘点改色求助

解决VGA显存绘制不同颜色点的问题

你的代码只能显示白色点,核心问题有两个:一是固定修改单个显存平面的整字节,未针对目标像素的具体位操作;二是未根据颜色值控制多个位平面的读写。以下是具体分析和修正方案:

问题根源

  1. 未定位像素的具体位:你计算了显存字节偏移di,但没处理像素在字节内的位位置,直接覆盖整个字节会导致同一字节内的8个像素被同时修改。
  2. 固定平面与颜色值:代码仅启用第1个位平面,且固定写入值4,只能修改像素颜色的某一位,其他位保留原有显存数据(若原本为1则显示白色)。

VGA 16色模式(640x480,模式12h)中,每个像素由4个位平面(0-3)的对应位共同决定颜色,4位组合对应0-15共16种颜色(0=黑,15=白)。

修正后的代码

以下函数通过bl寄存器接收0-15的颜色码,绘制指定颜色的点:

vmem1 PROC
    mov ax, 0A000h       ; 显存起始地址
    mov es, ax

    ; 计算显存字节偏移: di = y*(640/8) + x/8
    mov ax, dx
    mov bx, 80
    mul bx
    mov di, ax

    mov ax, cx
    mov bx, 8
    div bx
    add di, ax           ; di 是像素所在的显存字节偏移

    ; 计算像素在字节中的位位置: 7 - (x % 8),字节最高位对应最左像素
    mov ax, cx
    and ax, 7            ; ax = cx % 8
    mov cl, al
    mov al, 80h          ; 初始掩码为10000000b
    shr al, cl           ; al = 目标位的掩码

    mov ah, al           ; 保存掩码到ah
    mov cx, bx           ; cx = 传入的颜色值(bl)

    ; 遍历4个位平面(对应颜色的4位)
    mov dx, 3C4h         ; VGA序列寄存器端口
    mov si, 0            ; si = 当前平面索引(0-3)
plane_loop:
    mov al, 2            ; 序列寄存器索引2:平面掩码
    out dx, al
    inc dx
    mov al, 1 << si      ; 仅启用当前平面
    out dx, al
    dec dx

    ; 检查颜色的当前位是否为1
    mov al, cl
    shr al, si
    and al, 1
    jz clear_bit         ; 位为0则清除对应位
set_bit:
    mov al, ah
    or es:[di], al       ; 设置对应位
    jmp next_plane
clear_bit:
    mov al, ah
    not al
    and es:[di], al      ; 清除对应位
next_plane:
    inc si
    cmp si, 4
    jl plane_loop

    ret
vmem1 ENDP

关键步骤说明

  • 颜色参数:调用函数前将0-15的颜色码存入bl,比如mov bl, 4对应红色,mov bl, 14对应黄色。
  • 位掩码生成:通过cx%8计算像素在字节内的位置,生成仅目标位为1的掩码,确保只修改目标像素,不影响同字节的其他像素。
  • 位平面操作:遍历4个位平面,每个平面对应颜色的一位:
    1. 设置序列寄存器的平面掩码,仅允许当前平面读写;
    2. 根据颜色的对应位,决定是设置还是清除显存中的目标位。

内容的提问来源于stack exchange,提问作者user27789527

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:03:14