汇编语言8086

时间:2010-04-23 22:59:34

标签: assembly x86-16

我遇到了Assembly 8086的问题。我不知道如何使用2D数组。当我使用这样的时候 mov ar[cx][dx]我收到错误,当我想要数组中的SIDI时,它也会返回错误。

3 个答案:

答案 0 :(得分:11)

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

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

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

其中major_dimension是2D数组的维度之一(您使用的维度完全取决于数据在内存中的布局方式),element_size是每个元素的大小base 1}}是数组的开头,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加上次要索引,将其缩放到正确的元素大小(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

那就是你用来查找1D数组的地址。


并且基于以下评论:

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

会起作用,这是不对的(ar[bx][si]是与ar[bx+si]等效的masm特定语法。)

只需在arbx寄存器中添加si地址即可。它缩放bxsi注册表以考虑主要维度,它缩放bx+si值对于元素大小。所以它只能用于 bytes 的2D数组,其中主要维度是1,我很确定它会成为一维数组: - )

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

答案 1 :(得分:0)

我对你提出的确切问题并不是很清楚,但是你是否经历了这样的事情(使用基数/索引寻址模式)?

lea bx, array_base
mov si, array_index
mov ax, [bx][si]

答案 2 :(得分:0)

这可以帮到你。

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

下面是声明2D数组的代码,该数组以线性方式存储在存储器中。

像这样:

                +----------+----------+----------+----------+----------+----------+----------+
          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]第1行第1列,那么内存地址将是1024.要首先找到此条目,我必须计算行索引然后列索引。

计算行索引:

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

计算列索引:

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

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

即:1000 + 24 = 1024

  

.data

     

arr DWORD 0,1,2,3,4;这是具有4行的2D数组的声明,5个cols,每个条目需要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。

     

.CODE

     

mov ebx,2 * ROWSIZE;行索引= 2

     

mov esi,3; col index = 3

     

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