-1

我对 Assembly 8086 有疑问。我不知道如何使用二维数组。当我像这样使用 mov ar[cx][dx]时,我得到一个错误,当我想要我们SI并且DI在一个数组中它也返回一个错误。

4

3 回答 3

11

如果 CPU 以汇编语言提供数组查找语义,我会印象深刻。或者更确切地说,如果这意味着牺牲了更重要的东西,我会很生气。

在汇编中进行数组查找的一般方法是自己进行计算,将 2D 数组的两个索引转换为 1D 数组的单个索引,并调整元素大小。例如(伪代码):

ax = cx * major_dimension
ax = ax + dx
ax = ax * element_size
ax = peek[base+ax]

其中major_dimension是二维数组的维度之一(您使用的维度完全取决于数据在内存中的布局方式),element_size是每个元素的大小,base是数组的开头,cx/dx 是您的索引重新用于访问数组。

例如,如果您a[0-2][0-3]在内存位置有一个 3×4 ( ) 数组,0x0700并且这些是 32 位整数:

        +--------+--------+--------+--------+
0x0700: | a[0,0] | a[0,1] | a[0,2] | a[0,3] |
        +--------+--------+--------+--------+
0x0710: | a[1,0] | a[1,1] | a[1,2] | a[1,3] |
        +--------+--------+--------+--------+
0x0720: | a[2,0] | a[2,1] | a[2,2] | a[2,3] |
        +--------+--------+--------+--------+

要找到数组元素a[n,m],您计算主索引乘以四加上次索引,将其缩放到正确的元素大小(4 字节),然后添加基数。寻找元素a[2,1]

addr = base   + (n * 4 + m) * 4
     = 0x0700 + (2 * 4 + 1) * 4
     = 0x0700 + (8     + 1) * 4
     = 0x0700 + (9        ) * 4
     = 0x0700 + 36
     = 0x0700 + 0x24
     = 0x0724

那就是您用于查找一维数组的地址。


并且,根据以下评论:

ar   db   3dup(3dup(0))
     mov  ar[bx][si],al

会起作用,那不太正确(ar[bx][si]masm-specific 语法等效于ar[bx+si])。

所做的只是简单地将ar地址与bxsi寄存器相加。它不会缩放bx注册si以考虑主要尺寸,并且不会缩放bx+si元素大小的值。所以它只适用于主要维度为 1 的 2D字节数组,我很确定它会使其成为 1D 数组:-)

要适用于任何情况,您首先需要将bxsi(取决于哪个用于主要维度)乘以主要维度,然后再bx乘以si元素大小。

于 2010-04-23T23:37:04.667 回答
0

我不太清楚您要问的确切问题,但是您是否在追求这样的事情(使用基本/索引寻址模式)?

lea bx, array_base
mov si, array_index
mov ax, [bx][si]
于 2010-04-23T23:50:28.450 回答
0

这可以帮助你。

二维数组与一维数组一样存储在内存中,但将其表示为具有行和列。

下面是声明线性存储在内存中的二维数组的代码。

像这样:

                +----------+----------+----------+----------+----------+----------+----------+
          index | arr[0][0]| arr[0][1]| arr[0][2]| arr[0][3]| arr[0][4]| arr[1][0]| arr[1][1]| 
                +----------+----------+----------+----------+----------+----------+----------+
         value  |    0     |    1     |    2     |    3     |    4     |    10    |    11    |
                +----------+----------+----------+----------+----------+----------+----------+
 memory address | 1000     | 1004     | 1008     | 1012     | 1016     | 1020     | 1024     |
                +----------+----------+----------+----------+----------+----------+----------+

这里每行有 4 个条目和 5 列。

现在,如果我想定位值 11,arr[1][1] row 1 col 1,那么内存地址将是 1024。要首先定位这个条目,我必须计算行索引然后列索引。

计算行索引:

所以每行有 5 个条目,每个条目 4 个字节,因此每行将是 4*5=20 个字节。条目 11 在行索引 1 中,因此 1*20 = 20 将位于第 1 行。

计算列索引:

之后条目 11 位于列索引 1 中,因此 1*4= 4 位于列索引 1 处。我们将其乘以 4,因为我们已将其声明为 4 字节的 DWORD。

最后只需将结果相加(行索引+列索引)20+4 = 24。当我们将此添加到第一个条目的内存地址时,我们将跳转到条目11

即:1000+24 = 1024

。数据

arr DWORD 0, 1, 2, 3, 4 ; 这是具有 4 行、5 列的 2D 数组的声明,每个条目占用 4 个字节,因为它是一个 DWORD

      DWORD 10,11,12,13,14

      DWORD 20,21,22,23,24

      DWORD 30,31,32,33,34

ROWSIZE EQU SIZEOF arr ; 它是一个命名常量,这意味着每行有 20 个字节。每行有 5 个 cols 表示 5 个条目,每个条目有 4 个字节,因此 4*5 = 20。

。代码

移动 ebx, 2*ROWSIZE ; 行索引 = 2

移动 esi, 3 ; 列索引 = 3

mov eax, arr[ebx+esi*4] ; EAX = arr[2][3],这里当我们调用 arr[0] 时,它将是条目 0,因此条目 11 将是 arr[24]。这意味着从数组的起始内存地址跳过 24 个字节。

于 2015-07-09T04:26:47.290 回答