Ассемблер 8086 - PullRequest
       16

Ассемблер 8086

0 голосов
/ 24 апреля 2010

У меня проблема со сборкой 8086. Я не знаю, как использовать 2D-массив. Когда я использую, как это mov ar[cx][dx] Я получаю сообщение об ошибке, и когда я хочу получить SI и DI в массиве, он также возвращает ошибку.

Ответы [ 3 ]

11 голосов
/ 24 апреля 2010

Я был бы очень впечатлен процессором, обеспечивающим семантику поиска массива на его языке ассемблера. Или, скорее, я был бы раздражен, если бы это означало, что было принесено в жертву что-то более важное.

Общий способ поиска массива в сборке заключается в том, чтобы самостоятельно выполнить вычисление, чтобы превратить два индекса для двумерного массива в один индекс для одномерного массива и настроить размер элемента. Например (псевдокод):

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

, где major_dimension - это одно из измерений двумерного массива (используемое вами измерение полностью зависит от того, как данные располагаются в памяти), element_size - это размер каждого элемента, base - начало. массива, а cx / dx - индексы, которые вы используете для доступа к массиву.

Например, если у вас есть массив размером 3 на 4 (a[0-2][0-3]) в ячейке памяти 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

Тогда это адрес, который вы используете для поиска 1D массива.


И, исходя из комментария, что:

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

будет работать, это не совсем верно (ar[bx][si] - это синтаксис, зависящий от массы, эквивалентный ar[bx+si]).

Все, что нужно сделать, - это просто добавить адрес ar с регистрами bx и si. не масштабирует регистр bx или si, чтобы учесть основное измерение, и не масштабирует значение bx+si для размера элемента. Таким образом, он будет работать только как есть для двумерного массива байтов , где основной размер равен 1, что, я уверен, сделает его массивом 1D: -)

Чтобы работать в любом случае, вам сначала нужно умножить bx или si (в зависимости от того, что используется для основного измерения) на основное измерение, а затем bx и si на элемент размер.

0 голосов
/ 09 июля 2015

Это может помочь вам.

2D-массивы хранятся в памяти точно так же, как 1D-массив, но представляют их как строки и столбцы.

Ниже приведен код для объявления двумерного массива, который хранится в памяти линейно.

Как это:

                +----------+----------+----------+----------+----------+----------+----------+
          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. Чтобы найти эту запись, сначала нужно вычислить индекс строки, а затем индекс столбца.

Расчет индекса строки:

Таким образом, каждая строка имеет 5 записей по 4 байта, поэтому каждая строка будет иметь размер 4 * 5 = 20 байтов. Запись 11 находится в индексе строки 1, поэтому 1 * 20 = 20, что будет в строке 1.

Расчет индекса колонки:

После этого запись 11 входит в индекс столбца 1, поэтому 1 * 4 = 4, который находится в индексе столбца 1. Мы умножаем его на 4, потому что мы объявили его как DWORD, который имеет 4 байта.

Наконец, просто добавьте результаты (индекс строки + индекс col) 20 + 4 = 24. Когда мы добавим это к адресу памяти первой записи, мы перейдем к записи 11

То есть: 1000 + 24 = 1024

.данные

обр DWORD 0, 1, 2, 3, 4; Это объявление двумерного массива, имеющего 4 строки, каждая запись по 5 столбцов занимает 4 байта, потому что это DWORD

      DWORD 10,11,12,13,14

      DWORD 20,21,22,23,24

      DWORD 30,31,32,33,34

ROWSIZE EQU SIZEOF обр .; это именованная константа, которая означает, что каждая строка имеет 20 байтов. В каждой строке 5 столбцов означает 5 записей, и каждая запись имеет 4 байта, поэтому 4 * 5 = 20.

.code

mov ebx, 2 * ROWSIZE; индекс строки = 2

мов эси, 3; индекс col = 3

mov eax, arr [ebx + esi * 4]; EAX = arr [2] [3], здесь, когда мы вызываем arr [0], это будет запись 0, поэтому запись 11 будет arr [24]. Это означает, что пропустить 24 байта из начального адреса памяти массива.

0 голосов
/ 24 апреля 2010

Мне не совсем понятен точный вопрос, который вы задаете, но вы ищете что-то подобное (в режиме базовой / индексированной адресации)?

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