【问题标题】:Adding 2D arrays in Assembly (x86)在 Assembly (x86) 中添加二维数组
【发布时间】:2017-03-27 17:41:57
【问题描述】:

我必须添加两个 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

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

【问题讨论】:

  • 原谅我的无知,但有什么区别?无论顺序如何,您都可以逐个元素添加矩阵。
  • 令人印象深刻的是,您如何设法在单个代码中使用所有三种基本数据类型。 word 定义元素,dword 加载/存储它,byte 解决它。 (也许“使用”是夸大其词,“混合”更准确?)
  • @jester 我想在另一个一维数组中显示每一行的总和结果。列也一样。
  • 我明白了。嗯,有很多方法可以做到这一点,最直观的是使用两个嵌套循环。
  • 外循环迭代行(或列),内循环迭代每行(列)中的元素。在您的情况下,两个循环都转到3。您可以像在当前代码中一样访问项目,但要遍历需要添加行大小的列(例如3)。请注意,您需要按项目大小进行缩放(您忘记在代码中执行此操作)。

标签: arrays assembly x86


【解决方案1】:

a1 WORD 1,2,3
   WORD 4,2,3
   WORD 1,4,3

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

01 00 02 00 03 00 04 00 02 00 03 00 01 00 04 00 03 00

内存是按字节寻址的,所以如果你找到上面的每个元素,并计算它与第一个元素的位移(第一个位移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*3 | lea esi,[esi+eax] ; esi = y*3+x | mov ax,[a1+esi*2] ; loads [x,y] element from a1.

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

顺便说一句,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
    ...

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

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

【讨论】:

  • 这段代码中jnz命令的作用是什么?谷歌表示,当零标志不为零时,它会打破循环。这里,当 sum_row 不为零时,它会退出循环吗?我可以使用 mov 代替 lea 吗?谢谢你解释一下
  • jnz 之前影响 ZF 的最后一条指令是 dec ecx。当0 == ecx => ZF=1 or 0 != ecx => ZF=0。所以jnz 将在ecx 为2 和1 时跳转到列/行和标签,并在ecx 为0 时继续执行下一条指令。在求和之前有mov ecx,3,所以第一次@ 987654341@会做ecx = 2, ZF=0 ... =>“循环体”将被执行三次(使用调试器+逐步指令观察它的运行情况,包括最终dec之后的ZF更改)。 ... lea esi,[a1] == mov esi,offset a1 => 你可以替换这些简单的。
  • @Maya 但你不能替换那些 [mis] 使用地址数学单元进行简单计算,如 lea esi,[ebx+ebx*2],这将需要序列 mov esi,ebx / add esi,esi / add esi,ebx ... 最好采取深呼吸并再次reread the mov addressing modes,然后意识到leamov没有胆量,它会计算目标“地址”,但它不会联系内存芯片获取该地址的内容,而是存储计算的地址到目标寄存器。再次在调试器中观看它 = 简单。
  • 这里对jnz 的另一种解释:代码中的loop LOOPdec ecx / jnz LOOP 几乎相同。区别在于dec+jnz 会修改ZF 和其他标志(CF 除外,这是dec 的奇怪之处,它保留了CF),而loop 不会修改任何标志,而loop 在现代x86 上被人为减慢CPU,因为没有人在现代代码中使用它,但它有时用于遗留代码中的“延迟”循环,所以让它变慢有时会使旧的 SW 工作(这会全速失败loop)。 jnz 也是通用的,ZF 的条件跳转,而不仅仅是 for 循环。
猜你喜欢
  • 2017-03-26
  • 2019-04-22
  • 1970-01-01
  • 1970-01-01
  • 2014-10-03
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 2018-10-30
相关资源
最近更新 更多