抱歉标题,我无法想象用英语表达这种方式。 因此,我正在为一个课程编写一个小小的游戏,并且,在两个for循环中,我复制来自"炸弹的像素数据"像素矢量,到"区域"像素矢量,稍后将被绘制到屏幕上。在C中,它应该如下所示:
int x, y;
for(int i=0;i<32;i++)
for(int j=0;j<32;j++)
area[x+i][y+j]=bomb[i][j];
使用masm汇编程序和notepad ++编写代码,我得到了
mov ecx, 0 ; my i
outerloop:
cmp ecx, 32
je done
mov esi, 0 ; my j
innerloop:
mov ebx, sprite_width ; sprite_width=32
mov eax, ecx
mul ebx
add eax, esi
shl eax, 2
mov edi, bomb
add edi, eax
mov pixel, edi ; pixel = bomb[i][j]
mov ebx, area_width
mov eax, y
add eax, ecx
mul ebx
add eax, x
add eax, esi
shl eax, 2
mov edi, area
add edi, eax
mov eax, [pixel]
mov dword ptr [edi], eax ; should be area[x+i][y+j] = pixel
cmp esi, 32
je innerloopdone
inc esi
jmp innerloop
innerloopdone:
inc ecx
jmp outerloop
done:
在此之后,屏幕中的32x32区域应该看起来像炸弹,因为炸弹矢量是如何写的,但是我只看到一些绿色和一些蓝色。蓝色根本不在炸弹矢量中。循环/逻辑中是否有错误?
答案 0 :(得分:3)
由于你没有发布这些符号的定义,我只是猜测它们是如何定义的,我希望会有类似的东西:
area dd 640*480 dup (0) ; 640x480x32bpp "screen area"
area_width dd 640
sprite_width dd 32
sprite_height dd 32
bomb dd 32*32 dup (255) ; 32x32 red pixels as "bomb" gfx placeholder
然后,这应该足以以比您的提议更有效的方式绘制不透明的图形:
; initialize registers before drawing lines
; make edi = address area[y][x]
lea edi,[area]
mov ebx,[area_width]
mov eax,[y]
mul ebx
add eax,[x] ; eax = y*area_width + x
shl eax,2
add edi,eax ; edi = area + (y*area_width + x)*4
; make ebx = (area_width - sprite_width)*4
sub ebx,[sprite_width]
shl ebx,2
; make esi = address bomb[0][0]
lea esi,[bomb]
; make edx = number of lines
mov edx,[sprite_height] ; 32
line_loop:
; draw single line
mov ecx,[sprite_width]
rep movsd
; move to the next line (esi already updated, edi must advance)
add edi,ebx
; loop until all lines are drawn
dec edx
jnz line_loop
我没有调试它,所以可能有问题,但我没有MASM可以尝试。
关于您的原始代码,有一个反复出现的主题,您可以在其中编写以下内容:
mov edi, bomb
VS
mov eax, [pixel]
不幸的是,在MASM中这些是相同的,当您使用[]
名称时不需要symbol
内存访问,即mov edi,bomb
正在从内存加载值,而不是获取炸弹的地址。要获取地址,请使用MASM中的mov edi,OFFSET bomb
或lea edi,[bomb]
。
所以你混淆了这些,有时它看起来你确实想得到内存地址,有时候是值,有时你将地址存储到内存而不是值等等......
此外,我强烈建议您开始在符号周围使用[]
,即使MASM不需要它们,因此代码访问内存的行在视觉上更容易被发现,并且样式与间接寻址相同寄存器(即与mov eax,[ebx]
相同的样式,即使MASM需要方括号)。检查我的示例,我如何在每次内存访问时始终使用[]
(lea
除外,其中CPU将不访问内存,只计算地址,但这是由于lea
指令本身,它的参数仍然是memory-access-type)。
但最重要的是为您的平台找到一些有效的调试器,并学会使用它,因为在没有调试器的情况下进行汇编编程就像尝试组装机器人蒙上眼睛一样。你可以做到,但这要困难得多,需要很多技巧和经验。这是您目前的主要问题,代码的代码风格和效率就像问题的10%,无法调试您的代码是90%。