Многомерные массивы

Последнее обновление: 02.07.2023

Для ассемблера не существует многомерных массивов - все данные в наборе располагаются в памяти последовательно. Однако на логическом уровне может быть удобно представлять данные в виде многомерного массива. Например, возьмем двухмерные массивы, которые можно представить в виде таблицы, где строки представляют одно измерение, а столбцы - второе измерение:

numbers dword 1, 2, 3, 4
        dword 5, 6, 7, 8
        dword 9, 10, 11, 12

Здесь условно у нас есть три строки. В каждой строке по четрые столбца. В памяти такой набор данных будет располагаться последовательно, то есть фактически будет аналогичен следующему определению:

numbers dword 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12

Но в ряде задач довольно удобно работать с данными как с двухмерными массивами, например, при математических вычислениях с матрицами, для определения карт в играх и т.д. Соотвественно может возникнуть вопрос получения конкретного элемента из подобного двухмерного массива.

Если речь идет о двухмерном массиве/таблице, то формула получения элемента из определенной строки и столбца выглядит следующим образом:

element_address = base_address + (row_index * col_size + col_index) *element_size

Где base_address - адрес начала массива (его первого элемента), row_index - номер строки элемента, col_size - количество столбцов/элементов в строке, col_index - номер столбца элемента, а element_size - размер элементов в байтах. Нумерация строк и столбцов начинается с нуля, то есть номер первой строки или первого столбца - 0.

Например, возьмем выше определенный двухмерных массив numbers. Предположим, нам надо получить элемент в 2-й строке и 3-столбце (число 7). Тогда расчет адреса элемента будет выглядеть следующим образом:

element_address = адрес_numbers + (1 * 4 + 2) *4

То есть мы получим, что для получения адреса числа 7 нам надо к адресу массива numbers прибавить (1 * 4 + 2) *4 = 6 * 4 = 24 байт. Посмотрим, как это будет выглядеть в программе на ассемблере:

.data
    numbers dword 1, 2, 3, 4
            dword 5, 6, 7, 8
            dword 9, 10, 11, 12
    elemSize = 4    ; размер одного элемента - dword
    rows = 3        ; кол-во строк
    cols =  4       ; кол-во столбцов

    rowIndex dword 1     ; обращаемся к 2-й строке
    colIndex dword 2     ; обращаемся к 3-му столбцу

; Нам надо получить [rbx + (cols * rowIndex + colIndex) * elemSize] 
.code
main proc
    lea rbx, numbers    ; в RBX - адрес массива numbers
    xor rdx, rdx
    mov edx, rowIndex   ; в RDX индекс строки - rowIndex 
    imul edx, cols      ; cols * rowIndex
    add edx, colIndex   ; cols * rowIndex + colIndex         
    mov eax, [rbx + rdx * elemSize]    ; EAX = 7
    ret
main endp
end

В регистр RBX помещаем адрес массива numbers. Это будет базовый адрес, относительно которого будут идти все расчеты

lea rbx, numbers

Для вычисления эффективного адреса сначала в регистр EDX помещаем индекс строки элемента - переменную rowIndex

mov edx, rowIndex

Затем умножаем индекс строки на количество столбцов

imul edx, cols

Затем прибавляем к значению в EDX индекс столбца нужного элемента:

add edx, colIndex

Таким образом мы получили индекс элемента внутри массива numbers. Далее мы можем умножить этот индекс на размер элементов и прибавить к базовому адресу - адресу первого элемента в numbers. И таким образом получим адрес числа 7:

mov eax, [rbx + rdx * elemSize]

Опеределение массива

Стоит отметить, что если нам надо определить неинициализированный многомерный массив или многомерный массив, где все элементы имеют какое-то одно начальное значение, то мы можем использовать оператор dup:

numbers dword 3*4 dup (1)

Здесь определяется массив numbers из 12 элементов, каждый из которых равен 1.

MASM позволяет использовать вложенные выражения dup. Так, вместо предыдущего определения массива мы могли бы написать так:

numbers dword 3 dup (4 dup(1))

Можно прочитать эту запись так: определяем набор из 3 элементов, где каждый вложенный элемент представляет набор из 4 чисел dword. То есть по сути 3 строки, каждая из которых содержит 4 столбца.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850