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
几个非错误但可以优化的点
- 把
mov ebx, sprite_width和mov ebx, area_width移到循环外面,不用每次循环都重新加载:; 放到outerloop之前 mov ebx, sprite_width mov edx, area_width ; 用另一个寄存器存area_width,避免重复赋值 - 不需要用
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
相关产品推荐
相关产品推荐

