程序集从一个数组复制到另一个数组

Assembly copying from one array to another

对不起,这个标题,我想不出用英语表达的方式。 所以我正在为一门课程编写一个汇编小游戏,并且在两个 for 循环中,我将像素数据从 "bomb" 像素向量复制到 "area" 像素向量,稍后将被绘制到屏幕上。在 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 区域应该看起来像一个炸弹,因为炸弹矢量是如何写的,但是我只看到一些绿色和一些蓝色。蓝色甚至根本不在炸弹向量中。 loop/logic有没有错误?

由于您没有 post 这些符号的定义,我只是猜测它们是如何定义的,我希望是这样的:

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

    mov eax, [pixel]

不幸的是,在 MASM 中这些是相同的,当您使用 symbol 名称时不需要 [] 内存访问,即 mov edi,bomb 是从内存加载值,而不是获取地址炸弹。要获取地址,请在 MASM 中使用 mov edi,OFFSET bomb,或 lea edi,[bomb].

所以你混淆了那些,有时看起来你确实想要获取内存地址,有时想要值,有时你将地址而不是值存储到内存中,等等...

此外,我强烈建议您开始在符号周围使用 [] ,即使 MASM 不需要它们,这样访问内存的代码行在视觉上更容易被发现,并且样式与 indirect 相同通过寄存器寻址(即与 mov eax,[ebx] 相同的样式,其中甚至 MASM 也需要方括号)。检查我的示例,我如何在每次内存访问时始终如一地使用 []lea 除外,其中 CPU 将 访问内存,仅计算地址,但这是由于 lea 指令本身的性质,它的参数仍然是内存访问类型)。

但最重要的是为您的平台找到一些可用的调试器,并学习使用它,因为没有调试器的汇编编程就像试图 assemble 蒙住眼睛的机器人。您可以做到,但要困难得多,并且需要很多技巧和经验。这是你现在的主要问题,你代码的代码风格和效率大约是你问题的10%,无法调试你的代码是90%。