Доступ к элементам массива
Все элементы массива располагаются в памяти компьютера последовательно и то, как трактовать данную последовательность решает программист. Одну и ту же область памяти можно трактовать как одномерный массив, и одновременно те же самые данные могут трактоваться как двумерный массив. Все зависит только от алгоритма обработки этих данных в конкретной программе. Эти же соображения можно распространить и на индексы элементов массива. Наример, в программе статически определена последовательность данных: Mas dw 0,1,2,3,4,5,456,876,7,8752; 00 00 00 01 00 02 00 03 00 04 ; 00 05 01 С8 03 6С 00 07 22 30 Организовать доступ к предпоследнему байту можно следующим образом: 1) Mas[19]; =30 2) Mas[13h]; =C8 Mov esi,19 Mas[esi]; =30 4) Mov esi,6*2; 2 байта – размер элементов Mov ax, Mas[esi]; ax=01C8 Пусть эта последовательность чисел трактуется как одномерный массив. Размерность каждого элемента определяется директивой dw. В общем случае для получения адреса элемента в массиве необходимо начальный (базовый) адрес массива сложить с произведением индекса (номер элемента минус единица) этого элемента на размер элемента массива: база + (индекс*размер элемента)
Способы адресации, используемые при работе с массивами 1) индексная адресация со смещением — режим адресации, при котором полный адрес формируется из двух компонентов: l постоянного (базового) — указанием прямого адреса массива в виде имени идентификатора, обозначающего начало массива (смещения); l переменного (индексного) — указанием имени индексного регистра. К примеру: Mas dw 0,1,2,3,4,5 ... Mov si,4 ;поместить 3-й элемент массива mas в регистр ax: mov ax,mas[si]
2) базовая индексная адресация со смещением — режим адресации, при котором полный адрес формируется максимум из трех компонентов:
a. постоянного (необязательного компонента), в качестве которого может выступать прямой адрес массива в виде имени идентификатора (смещение), или непосредственное значение; b. переменного (базового) — указанием имени базового регистра; c. переменного (индексного) — указанием имени индексного регистра.
Этот вид адресации используется при обработке двухмерных массивов. Например: Mov eax,mas[bx][si] В качестве базового регистра может использоваться любой из восьми регистров общего назначения. В качестве индексного регистра также можно использовать любой регистр общего назначения, за исключением esp/sp.
Микропроцессор позволяет масштабировать индекс. Необходимость в масштабировании возникает при работе с массивами, которые имеют размер элементов, равный 2, 4 или 8 байтам. Например: Разработать программу, в которой просматривается массив, состоящий из слов, и производится сравнение этих элементов с нулем. Выводится соответствующее сообщение. Пример 6: Просмотр массива слов с использованием масштабирования ;prg_12_2.asm. Для DOS16. MASM MODEL small STACK 256 .data;начало сегмента данный ;тексты сообщений: mes1 db "не равен 0!$",10,13 mes2 db "равен 0!$",10,13 mes3 db 10,13,'Элемент $' mas dw 2,7,0,0,1,9,3,6,0,8;исходный массив .code ;.486;это обязательно start: mov ax,@data mov ds,ax;связка ds с сегментом данных xor ax,ax;обнуление ax prepare: mov сx,10;значение счетчика цикла в cx mov esi,0;индекс в esi compare: mov dx,mas[esi*2];первый элемент массива в dx cmp dx,0;сравнение dx с 0 je equal;переход, если равно not_equal:;не равно mov ah,09h;вывод сообщения на экран lea dx,mes3 int 21h mov ah,02h;вывод номера элемента массива на экран mov dx,si add dl,30h int 21h mov ah,09h lea dx,mes1 int 21h inc esi;на следующий элемент dec сх;условие для выхода из цикла jcxz exit;cx=0? Если да - на выход jmp compare;нет - повторить цикл equal:;равно 0 mov ah,09h;вывод сообщения mes3 на экран
lea dx,mes3 int 21h mov ah,02h mov dx,si add dl,30h int 21h mov ah,09h; вывод сообщения mes2 на экран lea dx,mes2 int 21h inc esi;на следующий элемент dec ex;все элементы обработаны? jcxz exit jmp compare exit: mov ax,4c00h;стандартный выход int 21h end main;конец программы
Возможны следующие случаи при адресации массивов: 1) если для описания адреса используется только один регистр, то такая адресация называется базовой адресацией и этот регистр рассматривается как базовый: ; переслать байт из области данных, адрес которой находится в ; регистре ebx mov al,[ebx]
2) если для задания адреса в команде используется прямая адресация (в виде идентификатора) в сочетании с одним регистром, то такая адресация называется индексной адресацией. Регистр считается индексным и поэтому можно использовать масштабирование для получения адреса нужного элемента массива: ;сложить содержимое eax с двойным словом в памяти по адресу ; mas + (ebx)*4 add eax,mas[ebx*4]
3) если для описания адреса используются два регистра, то такая адресация называется базово-индексной адресацией. Левый регистр рассматривается как базовый, а правый — как индексный. Базово-индексную адресацию можно сочетать с прямой адресацией или указанием непосредственного значения. Адрес тогда будет формироваться как сумма всех компонентов.
К примеру: mov ax,mas[ebx][ecx*2] ;адрес операнда равен [mas+(ebx)+(ecx)*2] ... sub dx,[ebx+8][ecx*4] ;адрес операнда равен [(ebx)+8+(ecx)*4]
Масштабирование эффективно только, когда размерность элементов массива равна 2, 4 или 8 байтам. Если же размерность элементов другая, то организовывать обращение к элементам массива нужно обычным способом. Пример 7: Обработка массива элементов с нечетной длиной. Размер элемента массива в три байта. Массив сформировать самостоятельно, следующим образом: первый элемент массива равен Е3 1111h=14 881 041d, все последующие трёхбитные элементы массива равны inc(E3 1111h). В памяти сформировать массив из 16 трёхбитных элемента. Увеличить на единицу в каждом элементе массива значение первого байта. Вывести измененный массив на экран в одну строку. Примечание: Е4 1111h=14 946 577d. ;--------------------------------------------------------------------------- ; Версия для Win32 (tri.asm) .386 .model flat, stdcall includelib import32.lib extrn ExitProcess:PROC extrn MessageBoxA:PROC
.data Ttl db 'Massiv',0h mas db 16 dup (3 dup (0)); 48 элементов в массиве ; следующую строчку 2 байта 0ah,0dh mes1 db 'Massiv: ',0ah,0dh Msg db 150 dup (?)
masVivod db 85 dup (?); var dd 0E31111h var2 dd? var3 dd 00000000h i db 1 N db 16 tabl db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h k dd 0
.code start: xor ecx,ecx;обнуление есx xor edx,edx mov cl,N;значение счетчика цикла в cl mov esi, 0;индекс начального элемента в si ;------------------------------------------------------------------------------------------------- ; Заполнение элементов массива значениями var E31111h++ mov eax,var mov var2,eax go2: xor eax,eax mov al,byte ptr [var+2]; al=E3h mov mas[esi],al inc esi mov al,byte ptr [var+1]; al=11h mov mas[esi],al inc esi mov al,byte ptr [var]; al=11h mov mas[esi],al inc esi inc var loopnz go2
;-------------------------------------------------------------------------------------------- ; Изменение первого байта в каждом элементе массива mov esi,0;0 в si xor ecx,ecx mov cl,N go: mov dl,mas[esi];первый байт поля в dl inc dl;увеличение dl на 1 (по условию) mov mas[esi],dl;заслать обратно в массив add esi,3;сдвиг на следующий элемент массива loop go;повтор цикла
mov cl,N mov edi,0 mov esi,0
go1: ;---------------------------------------------------------------------------- ; Переносим трёхбитное число из массива mas в регистр еах для перевода в ; десятичное число xor eax,eax xor ebx,ebx mov ah,mas[esi] mov al,mas[esi+1] mov bl,mas[esi+2] shl eax,8 add eax,ebx add esi,3 ;------------------------------------------------------------------------------- ; Перевод в десятичную систему исчисления трёхбайтного числа из eax и ; запись десятичного числа в память push esi mov ebx,eax xor eax,eax xor edx,edx xor edi,edi mov dl,i mov al,8 mul dl add eax,k mov edi,eax xor esi,esi mov esi,10 push edi mov eax,ebx lp2: xor edx,edx div esi xchg eax,edx add al,'0' mov byte ptr [Msg+edi],al xchg eax,edx dec edi or eax,eax jne lp2 ;------------------------------------------------------------------------------------- ; Ставим символ ";" в качестве разделителя после каждого числа pop edi mov byte ptr [Msg+edi+1],';' inc i inc k pop esi loopnz go1 ;--------------------------------------------------------------------------------------- ;вывод на экран получившегося массива push 0h push offset Ttl push offset [Msg+1] push 0h call MessageBoxA push 0h call ExitProcess end start
Результат: _______________________________________________________________ Самостоятельно на практике: Создать массив с элементами нечетной длины. Размер элемента массива в три байта. Массив сформировать самостоятельно, следующим образом: первый элемент массива равен Е3 1111h=14 881 041d, все последующие трёхбайтные элементы массива равны inc(E3 1111h). В памяти сформировать массив из 16 трёхбайтных элемента. Увеличить на единицу в каждом элементе массива значение второго байта. Вывести измененный массив на экран построчно так, чтобы в строке было 4 элемента массива.
Двумерные массивы Обращение к элементам двумерного массива в памяти как к строкам или как к столбцам зависит от алгоритма обработки двумерного массива. Если последовательность однотипных элементов в памяти трактуется как двумерный массив, расположенный по строкам, то адрес элемента (i, j) вычисляется по формуле: (база + количество_элементов_в_строке * размер_элемента * i+ +j* размер_элемента)
Здесь i = 0...n-l указывает номер строки, a j = 0...m-l указывает номер столбца. Например, пусть имеется массив чисел (размером в 1 байт) mas(i,j) с размерностью 4 X 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*1 = mas + 11
Организовывают адресацию двумерного массива, используя базово-индексную адресацию. При этом возможны два основных варианта выбора компонентов для формирования полного адреса: 4) сочетание прямого адреса, как базового компонента адреса, и двух индексных регистров для хранения индексов: mov ax,mas[ebx][esi] 5) сочетание двух индексных регистров, один из которых является и базовым, и индексным одновременно, а другой — только индексным: mov ax,[edi][esi]
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|