我对 Assembly 8086 有疑问。我不知道如何使用二维数组。当我像这样使用
mov ar[cx][dx]
时,我得到一个错误,当我想要我们SI
并且DI
在一个数组中它也返回一个错误。
3 回答
如果 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
地址与bx
和si
寄存器相加。它不会缩放或bx
注册si
以考虑主要尺寸,并且不会缩放bx+si
元素大小的值。所以它只适用于主要维度为 1 的 2D字节数组,我很确定它会使其成为 1D 数组:-)
要适用于任何情况,您首先需要将bx
或si
(取决于哪个用于主要维度)乘以主要维度,然后再bx
乘以si
元素大小。
我不太清楚您要问的确切问题,但是您是否在追求这样的事情(使用基本/索引寻址模式)?
lea bx, array_base
mov si, array_index
mov ax, [bx][si]
这可以帮助你。
二维数组与一维数组一样存储在内存中,但将其表示为具有行和列。
下面是声明线性存储在内存中的二维数组的代码。
像这样:
+----------+----------+----------+----------+----------+----------+----------+
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 个字节。