int 10h模式13h下直接写入显存绘制像素失败求助
问题分析与解决方案
首先,你的代码存在两个关键问题导致绘制无效,我们逐一拆解解决:
1. 函数调用的参数入栈顺序完全颠倒
你的drawFaster过程定义的参数栈偏移是:
bp + 2:行(dx)bp + 4:列(cx)bp + 6:颜色
但实模式下的栈是先进后出的结构,参数入栈顺序必须和偏移定义相反——最后被push的参数会位于栈顶(对应bp+2)。你当前的调用代码入栈顺序完全搞反了:
push dx ; 行,最先入栈 → 实际对应 bp+6 push cx ; 列,中间入栈 → 实际对应 bp+4 push ax ; 颜色,最后入栈 → 实际对应 bp+2
正确的入栈顺序应该是先push颜色,再push列,最后push行,这样栈顶的行参数才会匹配bp+2的定义:
push bp mov ax, 30 ; 颜色 push ax mov cx, 50 ; 列 push cx mov dx, 50 ; 行 push dx call drawFaster pop bp
2. 内存操作的操作数大小不明确(导致[es:bx]无法运行的问题)
在16位汇编中,直接写mov [es:bx], 30时,汇编器会默认按**字(2字节)**处理操作,但VGA 13h模式下每个像素仅占1字节,这种字操作会覆盖相邻像素,甚至因操作数大小不匹配引发错误。
你看到mov [es:0], 30能“正常运行”,其实是汇编器把它解析为字操作,向显存起始地址写入了0x001E,相当于同时修改了第0和第1个像素,这并非正确的单像素绘制方式。正确写法需要显式指定字节操作:
mov ax, 0A000H mov bx, 0 mov es, ax mov byte ptr [es:bx], 30 ; 明确指定为字节操作
值得庆幸的是,你的drawFaster过程中mov [es:di], al是正确的——因为al是8位寄存器,汇编器会自动识别为字节操作,这部分无需修改。
额外验证建议
你可以先简化测试,在drawFaster里写死坐标和颜色:
drawFaster proc pushad mov ax, 0A000h mov es, ax mov di, 0 ; 固定屏幕左上角坐标 mov al, 30 ; 固定颜色 mov [es:di], al popad ret 6 endp
调用这个版本后,如果屏幕左上角出现对应颜色,说明显存地址和基础操作逻辑是正确的,再逐步恢复参数逻辑,能更高效地排查问题。
内容的提问来源于stack exchange,提问作者Guy Sudai
相关产品推荐
相关产品推荐

