汇编绘图遇A2155错误:16位寄存器配32位地址及INT 10h使用疑问
汇编绘图问题解答
一、A2155错误的原因与修复
错误提示A2155 cannot use 16-bit register with a 32-bit address是因为你使用的Irvine32.inc属于32位汇编环境,默认采用32位寻址规则。你代码里用16位寄存器DI对32位段寄存器ES进行寻址,这在32位环境下是不允许的。
修复要点:
- 将16位寄存器
DI替换为32位寄存器EDI - 把变量
num的定义改为32位类型(dd),避免16位/32位寄存器混用引发的寻址问题 - 计算显存地址时,遵循32位寻址的语法规范
二、关于INT 10h的疑问
你必须调用INT 10h,核心原因有两个:
- 设置图形模式:系统默认启动为文本模式,显存结构和图形模式完全不同。必须通过INT 10h的
AH=00h功能切换到图形模式(比如AL=13h对应320×200 256色模式,是最常用的BIOS图形模式)。 - 两种绘图方式的依赖:
- 直接写显存:切换到图形模式后,可以直接往显存地址(13h模式下对应
0A000h段,32位环境中可用0A0000h线性地址)写入像素颜色,但需要自己计算每个像素的地址公式:像素地址 = y * 屏幕宽度 + x - 调用INT 10h绘图:使用
AH=0Ch功能,传入AL=颜色、CX=x坐标、DX=y坐标即可完成像素绘制,无需手动计算显存地址,操作更简单
- 直接写显存:切换到图形模式后,可以直接往显存地址(13h模式下对应
三、修正后的代码
INCLUDE Irvine32.inc .data num dd 0 ; 改为32位变量,适配32位汇编环境 .code main PROC ; 调用INT 10h设置320×200 256色图形模式 mov ah, 00h mov al, 13h int 10h L1: mov eax, num ; 将x值放入EAX寄存器 mul eax ; 计算x²,结果存储在EAX(x值较小,无需使用EDX) mov ebx, 2 mul ebx ; 计算2x²,结果即为y值,存储在EAX ; 检查y值是否超出屏幕高度(13h模式下y最大为199) cmp eax, 199 jge ExitLoop ; 超出屏幕范围则退出循环 ; 计算像素在显存中的偏移地址:EDI = y*320(屏幕宽度) + x mov ebx, 320 mul ebx ; EAX = y * 320 add eax, num ; EAX += x,得到最终偏移地址 mov edi, eax ; 写入像素颜色 mov al, 0111b ; 设置像素颜色为亮白色 mov es, 0A000h ; 切换ES到13h模式的显存段地址 mov byte ptr es:[edi], al ; 写入像素(13h模式下每个像素占1字节) inc num cmp num, 320 ; x值最大为319(屏幕宽度上限) jl L1 ExitLoop: ; 等待用户按键,避免程序直接退出导致屏幕乱码 mov ah, 00h int 16h ; 恢复文本模式 mov ah, 00h mov al, 03h int 10h ret main ENDP END main
补充说明
- 原代码错误地将
DS切换到0C000h,这是文本模式的显存段,图形模式下应使用0A000h - 计算
y=2x²时,x值不能过大,否则y会超出屏幕范围(比如x=10时,2*10²=200,超过13h模式的y上限199),需根据所选图形模式调整x的范围 - 代码末尾增加了等待按键和恢复文本模式的逻辑,避免程序结束后屏幕显示异常
内容的提问来源于stack exchange,提问作者cptalpdeniz
相关产品推荐
相关产品推荐

