16位NASM汇编PS/2鼠标驱动在VGA模式0x12下覆盖屏幕内容问题
解决VGA模式0x12下PS/2鼠标光标覆盖屏幕背景的问题
我正在为运行于VGA模式0x12(640x480,16色)的自定义操作系统开发16位NASM汇编的PS/2鼠标驱动。驱动已实现鼠标初始化、事件处理,并用位图掩码(mousebmp)绘制8×11像素的光标。光标移动功能正常,但会覆盖屏幕原有内容,无法保留背景。

问题原因
当前HideCursor函数直接用黑色(0x00)覆盖原光标位置,这会清除该区域的原有背景内容。正确的逻辑应该是先保存光标覆盖区域的背景像素,隐藏光标时恢复这些像素,而非用固定颜色覆盖。
解决方案
添加背景缓冲区保存光标区域的像素数据,修改DrawCursor和HideCursor函数的逻辑,实现背景的保存与恢复:
1. 添加背景缓冲区
在.data段中新增用于存储光标背景的缓冲区:
section .data MOUSEFAIL db "An unexpected error happened!", 0 MOUSEINITOK db "Mouse initialized!", 0x0F, 0 ButtonStatus dw 0 MouseX dw 0 MouseY dw 0 ; 新增:保存光标背景的缓冲区,8*11=88字节 cursorBackground times WCURSOR*HCURSOR db 0 mousebmp: db 0b10000000 db 0b11000000 db 0b11100000 db 0b11110000 db 0b11111000 db 0b11111100 db 0b11111110 db 0b11111000 db 0b11011100 db 0b10001110 db 0b00000110
2. 修改DrawCursor函数
先保存光标区域的背景像素,再绘制光标:
DrawCursor: pusha mov cx, [MouseX] mov dx, [MouseY] mov si, mousebmp mov di, cursorBackground ; 指向背景缓冲区 ; 第一步:保存光标区域的背景 .saveLoopY: mov bp, WCURSOR add bp, cx mov bx, cx .saveLoopX: mov ah, 0x0D ; BIOS功能:读取指定位置的像素 int 0x10 mov [di], al ; 将读取的像素存入缓冲区 inc bx inc di cmp bx, bp jb .saveLoopX inc dx inc si mov bp, HCURSOR add bp, [MouseY] cmp dx, bp jb .saveLoopY ; 第二步:绘制光标 mov cx, [MouseX] mov dx, [MouseY] mov si, mousebmp mov ah, 0x0C ; BIOS功能:写入像素 .drawLoopY: mov bp, WCURSOR add bp, cx mov bx, cx mov al, 0x0F ; 光标颜色 .drawLoopX: test byte [si], 0x80 ; 检查当前位图位是否为1(需要绘制) jz .skipDraw int 0x10 ; 绘制像素 .skipDraw: inc bx shl byte [si], 1 ; 移位处理下一位 cmp bx, bp jb .drawLoopX inc dx inc si mov bp, HCURSOR add bp, [MouseY] cmp dx, bp jb .drawLoopY .end: popa ret
3. 修改HideCursor函数
从缓冲区读取保存的背景像素,恢复原屏幕内容:
HideCursor: pusha mov cx, [MouseX] mov dx, [MouseY] mov di, cursorBackground ; 指向背景缓冲区 mov ah, 0x0C ; BIOS功能:写入像素 .restoreLoopY: mov bp, WCURSOR add bp, cx mov bx, cx .restoreLoopX: mov al, [di] ; 取出保存的背景像素 int 0x10 ; 恢复像素到屏幕 inc bx inc di cmp bx, bp jb .restoreLoopX inc dx mov bp, HCURSOR add bp, [MouseY] cmp dx, bp jb .restoreLoopY .end: popa ret
代码说明
cursorBackground缓冲区:存储光标覆盖区域的88个像素值(8×11),确保每次绘制光标前都能保存当前背景DrawCursor函数:先调用BIOS 0x10的0x0D功能读取像素保存到缓冲区,再执行原有的光标绘制逻辑HideCursor函数:不再用固定颜色覆盖,而是从缓冲区读取保存的像素,调用BIOS 0x10的0x0C功能恢复原背景内容
内容的提问来源于stack exchange,提问作者PRoX
相关产品推荐
相关产品推荐

