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

MASM汇编中数组像素拷贝逻辑错误排查求助

分析你的汇编代码错误

首先,核心问题出在二维数组的地址计算逻辑上——你把行和列的索引搞反了,导致写入area数组的位置完全错误,甚至可能越界访问到其他内存区域,才出现了bomb数组里根本没有的蓝色像素。

先理清楚二维数组的内存规则

不管是C还是汇编,二维数组都是行优先存储的,简单说就是先存完一行的所有元素,再存下一行。所以array[row][col]的内存偏移公式是:

偏移 = row * 数组宽度 + col

每个像素是4字节(DWORD),最后用shl eax, 2来乘4,这部分你是做对的。

你的代码和C逻辑不匹配

你的C代码写的是:

area[x+i][y+j] = bomb[i][j];

但你的汇编计算area偏移时,逻辑是:

mov eax, y
add eax, ecx   ; 算出 y + i(当成行索引)
mul ebx        ; ebx是area_width,得到 (y+i)*area_width
add eax, x
add eax, esi   ; 加上 x + j(当成列索引)

这对应的是area[y+i][x+j] = bomb[i][j],和你写的C代码逻辑完全相反!

如果你的实际需求是把炸弹画在屏幕的(x,y)坐标(x是水平偏移,y是垂直偏移),那正确的C代码应该是area[y+i][x+j] = bomb[i][j](y对应行,x对应列);如果非要和你写的C代码逻辑一致,那汇编里的area偏移计算要改成:

mov ebx, area_width
mov eax, x
add eax, ecx       ; 行索引 = x + i
mul ebx            ; 行偏移 = (x+i)*area_width
add eax, y
add eax, esi       ; 加上列索引 y + j
shl eax, 2

几个非错误但可以优化的点

  1. 把mov ebx, sprite_width和mov ebx, area_width移到循环外面,不用每次循环都重新加载:
    ; 放到outerloop之前
    mov ebx, sprite_width
    mov edx, area_width    ; 用另一个寄存器存area_width,避免重复赋值
    
  2. 不需要用pixel变量中转,直接读写内存更高效:
    ; 去掉 mov pixel, edi 和 mov eax, [pixel]
    mov eax, [edi]  ; 直接从bomb的地址读取像素值
    mov dword ptr [edi_area], eax
    

循环边界是对的

你的循环边界判断cmp esi,32 je innerloopdone没问题,因为j从0到31,刚好执行32次循环,符合for(j=0;j<32;j++)的逻辑。

修正行和列的地址计算后,应该就能正确显示炸弹图案,不会再出现奇怪的蓝色像素了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:04:10