Assembly copying from one array to another

2019-08-24 05:34发布

and sorry for the title, i couldn't imagine a way to express this in english. So i'm writing a little game in assembly for a course, and, inside of two for loops, i copy the pixel data from the "bomb" vector of pixels, to the "area" vector of pixels, which will later be drawn to the screen. In C, it should look like this:

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];

Using masm assembler and notepad++ to write the code, i got

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:

After this, the 32x32 area in the screen should look like a bomb, because of how the bomb vector is written, however i only see some green and some blue. Blue is not even in the bomb vector at all. Is there any mistake in the loop/logic?

1条回答
Summer. ? 凉城
2楼-- · 2019-08-24 06:09

As you didn't post definitions of those symbols, I'm just guessing how they were defined, I would expect something like:

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

Then this should be enough to draw non-transparent piece of graphics in a bit more efficient way than your proposal:

    ; 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

I didn't debug it, so there may be a problem, but I don't have MASM to try.


About your original code, there's recurring theme where you write things like:

    mov edi, bomb

vs

    mov eax, [pixel]

Unfortunately in MASM these are identical, the [] memory access is not needed when you use symbol name, i.e. the mov edi,bomb is loading value from memory, not getting address of bomb. To get address use mov edi,OFFSET bomb in MASM, or lea edi,[bomb].

So you mix up those, and sometimes it looks like you did want to get memory address, and sometimes value, and sometimes you store address into memory instead of value, etc...

Also I strongly suggest you to start using [] around symbols even when the MASM doesn't require them, so the lines in code accessing memory are visually easier to spot, and the style is identical with indirect addressing through registers (i.e. same style as mov eax,[ebx], where even MASM needs square brackets). Check my example, how I consistently use [] around every memory access (except lea, where the CPU will not access memory, only calculate address, but that's due to nature of lea instruction itself, the argument for it is still memory-access-type).

But most importantly find some working debugger for your platform, and learn to use it, because programming in assembly without debugger is like trying to assemble robot blindfolded. You can do it, but it's much more difficult and requires lot of skill and experience. This is your major problem right now, the code style and efficiency of your code is like 10% of your problem, not being able to debug your code is 90%.

查看更多
登录 后发表回答