Двухмерные массивы

С представлением одномерных массивов в программе на ассемблере и организацией их обработки все достаточно просто. А как быть если программа должна обрабатывать двухмерный массив? Все проблемы возникают по-прежнему из-за того, что специальных средств для описания такого типа данных в ассемблере нет. Двухмерный массив нужно моделировать. На описании самих данных это почти никак не отражается — память под массив выделяется с помощью директив резервирования и инициализации памяти.

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

Если последовательность однотипных элементов в памяти трактуется как двухмерный массив, расположенный по строкам, то адрес элемента (i, j) вычисляется по формуле

(база + количество_элементов_в_строке * размер_элемента * i+j)

Здесь i = 0...n–1 указывает номер строки, а j = 0...m–1 указывает номер столбца.

Например, пусть имеется массив чисел (размером в 1 байт) mas(i, j) с размерностью 4 на 4 (i= 0...3, j = 0...3):

23 04 05 67 05 06 07 99 67 08 09 23 87 09 00 08

В памяти элементы этого массива будут расположены в следующей последовательности:

23 04 05 67 05 06 07 99 67 08 09 23 87 09 00 08

Если мы хотим трактовать эту последовательность как двухмерный массив, приведенный выше, и извлечь, например, элемент mas(2, 3) = 23, то проведя нехитрый подсчет, убедимся в правильности наших рассуждений:

Эффективный адрес mas(2, 3) = mas + 4 * 1 * 2 + 3 = mas + 11

Посмотрите на представление массива в памяти и убедитесь, что по этому смещению действительно находится нужный элемент массива.

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

· сочетание прямого адреса, как базового компонента адреса, и двух индексных регистров для хранения индексов:

mov ax,mas[ebx][esi]

· сочетание двух индексных регистров, один из которых является и базовым и индексным одновременно, а другой — только индексным:

mov ax,[ebx][esi]

В программе это будет выглядеть примерно так:

;Фрагмент программы выборки элемента массива mas(2,3) и его обнуления.datamas db23,4,5,67,5,6,7,99,67,8,9,23,87,9,0,8i=2j=3.code... mov si,4*1*i mov di,j mov al,mas[si][di];в al элемент mas(2,3)...

В качестве законченного примера рассмотрим программу поиска элемента в двухмерном массиве чисел. Элементы массива заданы статически.

Пример: Поиск элемента в двухмерном массивеMASMMODEL smallSTACK 256.data;матрица размером 2x5 — если ее не инициализировать,;то для наглядности она может быть описана так:;array dw 2 DUP (5 DUP (?));но мы ее инициализируем:array dw 1,2,3,4,5,6,7,3,9,0;логически это будет выглядеть так:;array= {1 2}; {3 4}; {5 6}; {7 3}; {9 0} elem dw 3;элемент для поискаfailed db 0ah,0dh,'Нет такого элемента в массиве!','$'success db 0ah,0dh,'Такой элемент в массиве присутствует ','$'foundtime db?;количество найденных элементовfnd db ' раз(а)',0ah,0dh,'$'.codemain: mov ax,@data mov ds,ax xor ax,ax mov si,0;si=столбцы в матрице mov bx,0;bx=строки в матрице mov cx,5;число для внешнего цикла (по строкам)external:;внешний цикл по строкам mov ax,array[bx][si];в ax первый элемент матрицы push cx;сохранение в стеке счётчика внешнего цикла mov cx,2;число для внутреннего цикла (по столбцам) mov si,0iternal:;внутренний цикл по строкам inc si;передвижение на следующий элемент в строке;сравниваем содержимое текущего элемента в ax с искомым элементом: cmp ax,elem;если текущий совпал с искомым, то переход на here для обработки,;иначе цикл продолжения поиска je here;иначе — цикл по строке cx=2 раз loop iternalhere: jcxz move_next;просмотрели строку? inc foundtime;иначе увеличиваем счётчик совпавшихmove_next:;продвижение в матрице pop cx;восстанавливаем CX из стека (5) add bx,1;передвигаемся на следующую строку loop external;цикл (внешний) cmp foundtime,0h;сравнение числа совпавших с 0 ja eql;если больше 0, то переходnot_equal:;нет элементов, совпавших с искомым mov ah,09h;вывод сообщения на экран mov dx,offset failed int 21h jmp exit;на выходeql:;есть элементы, совпавшие с искомым mov ah,09h;вывод сообщений на экран mov dx,offset success int 21h mov ah,02h mov dl,foundtime add dl,30h int 21h mov ah,09h mov dx,offset fnd int 21hexit:;выход mov ax,4c00h;стандартное завершение программы int 21hend main;конец программы

При анализе работы программы не забывайте, что в языке ассемблера принято элементы массива нумеровать с 0. При поиске определенного элемента массив просматривается от начала и до конца. Приведенная программа сохраняет в поле foundtime количество вхождений искомого элемента в массив. В качестве индексных регистров используются si и bx.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: