在 Assembly (x86) 中添加 2D 数组

May*_*aya 2 arrays x86 assembly

我必须添加两个 3*3 的单词数组并将结果存储在另一个数组中。这是我的代码:

.data 
a1 WORD 1,2,3
   WORD 4,2,3
   WORD 1,4,3

a2 WORD 4, 3, 8
   WORD 5, 6, 8
   WORD 4, 8, 9

a3 WORD DUP 9(0)
.code
main PROC
    mov eax,0;
    mov ebx,0;
    mov ecx,0;
    mov edx,0;
    mov edi,0;
    mov esi,0;
    mov edi,offset a1
    mov esi,offset a2
    mov ebx, offset a3
    mov ecx,LENGTHOF a2

    LOOP:
    mov eax,[esi]
    add eax,[edi]
    mov [ebx], eax
    inc ebx
    inc esi
    inc edi

    call DumpRegs
    loop LOOP

    exit
main ENDP

END main
Run Code Online (Sandbox Code Playgroud)

但这是 a2 和 a1 的所有元素的总和。如何逐行、逐列添加它们?我想在另一个一维数组中显示每行的总和结果(列相同)。

Ped*_*d7g 5

a1 WORD 1,2,3
   WORD 4,2,3
   WORD 1,4,3
Run Code Online (Sandbox Code Playgroud)

将编译为字节(十六进制):

01 00 02 00 03 00 04 00 02 00 03 00 01 00 04 00 03 00
Run Code Online (Sandbox Code Playgroud)

内存是按字节寻址的,所以如果你找到上面的每个元素,并计算它与第一个元素的位移(第一个元素位移了 0 个字节,即它的地址是a1+0),你应该看到一个模式,如何计算位移特定的 [y][x] 元素(x 是列号 0-2,y 是行号 0-2...如果你决定这样做,这取决于你,什么是列/行,但通常人们倾向于考虑内存中的连续元素为“一行”)。

注意基本类型字节大小,您以各种方式将其混合在一起,重新阅读一些课程/教程,了解 qword/dword/word/byte 有何不同,以及如何调整指令以使用正确的内存大小,以及如何正确计算地址(以及地址的大小eax以及如何使用其中较小的部分)。

如果您自己无法解决:

位移 = (y * 3 + x) * 2 => *2 因为元素是word,每个占用两个字节。y * 3 因为单行有 3 个元素长。

在 ASM 指令中可以实现例如...

如果 [x,y] 是 [eax,ebx],则此计算可以如下完成lea esi,[ebx+ebx*2] ; esi = y*3lea esi,[esi+eax] ; esi = y*3+x| mov ax,[a1+esi*2] ; loads [x,y] element from a1

现在,如果您知道如何计算特定元素的地址,则可以在每个元素加载之前循环执行所有计算,或者只在 head 中计算地址的差异并编写第一个元素的地址计算(行的开头) /column),然后mov+ 2x add,对接下来的两个元素进行硬编码偏移(为 3 个元素制作循环比编写没有循环的展开代码更麻烦),并对所有三列/行重复此操作并存储结果。

顺便说一句,那call DumpRegs......没有产生您所期望的结果?调试代码的方式有点乏味,可能值得花一些时间让调试器工作。


我无法帮助自己,但还是写了它,因为它是一段很有趣的短代码,但如果你只是复制它,而不是把它剖析成原子并完全理解它是如何工作的,你以后会后悔的):

column_sums: DW 0, 0, 0
row_sums:    DW 0, 0, 0
    ...
    ; columns sums
    lea   esi,[a3]    ; already summed elements of a1 + a2
    lea   edi,[column_sums]
    mov   ecx,3       ; three columns to sum
sum_column:
    mov   ax,[esi]    ; first element of column
    add   ax,[esi+6]  ; 1 line under first
    add   ax,[esi+12] ; 2 lines under
    mov   [edi],ax    ; store result
    add   esi,2       ; next column, first element
    add   edi,2       ; next result
    dec   ecx
    jnz   sum_column
    ; rows sums
    lea   esi,[a3]    ; already summed elements of a1 + a2
    lea   edi,[row_sums]
    mov   ecx,3       ; three rows to sum
sum_row:
    mov   ax,[esi]    ; first element of row
    add   ax,[esi+2]  ; +1 column
    add   ax,[esi+4]  ; +2 column
    mov   [edi],ax    ; store result
    add   esi,6       ; next row, first element
    add   edi,2       ; next result
    dec   ecx
    jnz   sum_row
    ...
Run Code Online (Sandbox Code Playgroud)

(没有调试它,所以可能会出现错误,再加上这期望 a3 包含正确的元素和,而您的原始代码不会产生这些元素和,所以您必须先修复它......这段代码确实包含很多提示,如何修复原版的每个问题)

现在,我为夺走了你写这篇文章的乐趣而感到内疚……没关系,我相信你可以找到更多的任务来练习这一点。问题是你是否掌握了它的原理。如果没有,请询​​问哪一部分令人困惑以及您目前如何理解它。