Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
flor_apparato-orientirovnnoe_prog.doc
Скачиваний:
89
Добавлен:
15.06.2014
Размер:
926.72 Кб
Скачать

4.2. Использование индексной адресации данных

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

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

На ассемблере NASM операнды, задаваемые индексным способом адресации, записываются в форме [имя_массива + индексный регистр] или [смещение + индексный регистр]. Первый вариант широко используется для именованных областей, второй наблюдается при просмотре исполняемых файлов с помощью дизассемблеров и отладчиков, когда нет достаточной информации об исходных программах на языке ассемблера. В частности, индексному способу адресации отвечают обозначения операндов [tabla+ESI], [buffer+EDX] и т.п.

На ассемблерах MASM и TASM индексный способ адресации операнда позволяется и в форме имя_массива [индексный регистр], что практически делает его внешне совпадающим с традиционной формой записи индексированных переменных в алголоподобных языках.

Запишем для сравнения простейшую программу суммирования элементов массива, где каждый элемент занимает один байт (это предельно упрощенный пример, т.к. отдельные байты позволяют записывать числа в чрезвычайно ограниченном диапазоне от - 128 до +127). Далее представлена программа в двух вариантах - на языке ассемблера (в первом столбце) и на языке Паскаль (во втором столбце):

mov eax,0 sum:=0;

repeat

mov esi, 0 i:=0;

met: add eax, [tabla + esi] sum:=sum+tabla[i];

inc esi i:=i+1;

cmp esi, 10 until i >= 10;

jl met

Как видим, сходство поразительное и отличия, в основном, заключаются в средствах организации цикла, а не в форме записи доступа к элементу массива.

При практическом использовании индексного способа адресации следует иметь в виду, что недопустимо применение в качестве индексного 8-битного регистра. Регистры же, которые можно применять в косвенно-регистровой адресации, также хорошо подходят и для индексной адресации. (Напомним, что этими регистрами являются EAX, EBX, ECX, EDX, ESI, EDI.) В 16-битной архитектуре для индексной адресации были назначены только два регистра SI и DI, отсюда возникло и их наименование (Source Index и Destination Index). В той же 16-битной архитектуре допускалось использование в качестве индексных и регистров BX, BP. Практически же в этой исходной примитивной архитектуре все регистры были специализированы в большей или меньшей степени.

При широком использовании индексного способа адресации следует постоянно учитывать, что значение индексного регистра задает смещение в байтах относительно начала массива, а не порядковый номер элемента в этом массиве. Совпадение того и иного имеет место только в том случае, когда элементы массива однобайтовые. (Так оно и было в приведенных примерах.) Если же элементы массива представляются 16-битными словами, то вместо приращения индекса на единицу необходимо увеличивать его на 2 (два байта занимает каждый элемент). Когда размер элемента массива есть N байтов, то следует изменять значение индексного регистра на N.

В качестве примера практического использования индексной адресации, рассмотрим задачу поиска максимального в массиве чисел основного для 32-битной архитектуры размера числовых элементов, составляющего 4 байта (размер типа int для этой архитектуры). Пример такой программы приведен в листинге 4.2.1.

GLOBAL _start

SEGMENT .text

_start: mov esi, 0 ; esi=valindex = 0

mov eax, [narray+0] ; или просто [narray]; eax - текущее значение max

met1: cmp eax, [narray+esi] ; сравнение max и narray[index]

jg next

mov eax, [narray+esi] ; поместить narray[index] в edx

next: add esi, 4 ; valindex - приходится увеличивать на 4 байта

; - размер места числа в памяти

cmp esi, 10*4 ; проверены ли все 10 элементов массива?

jl met1

; полученный max в регистре eax

mov esi,10 ; base of position digit system

mov ecx, 0 ; reset digit counter

pov: mov edx, 0 ; null into left part of devident

div esi ; divide for next digit = rest

add dl, '0'

push edx

inc ecx ; step into counter

cmp eax, 0

jne pov

mov [cnt], ecx

mov ebx, formax

izv: pop edx

mov byte [ebx],dl ; digit into array for text value

inc ebx

loop izv ; izv,ecx

;--- write(1, txtmes, lenmes+[cnt]) == <4>(ebx, ecx, edx)

mov eax,4 ; N function=write

mov ebx,1 ; N handle=1 (stdout)

mov edx,[cnt] ; number of byte

add edx, lenmes

mov ecx, txtmes ; address of txtmes (и далее formax)

int 80h

mov eax,1

int 80h ; function=exit for Linux

SEGMENT .data

narray dd 3,17,-5,27,0,-11,17,33,-1,9

txtmes db 'Максимальное число в массиве есть '

lenmes equ $-txtmes

formax times 10 db ' '

cnt dd 0

Листинг 4.2.1.Поиск максимального в массиве чисел

В этой программе значение индекса (смещения индексируемого элемента массива) помещается в регистр ESI. Регистр EAX выделен для размещения в нем будущего значения максимального элемента. Значение индекса, с учетом размеров элементов массива в 4 байта, увеличивается на 4 командой ADD ESI, 4. При проверке выхода значения индекса за пределы массива в качестве значения для сравнения используется не число элементов массива, а его произведение на размер элементов. Это произведение явно записывается в операнде с непосредственной адресацией команды сравнения cmp esi, 10*4. Тем самым, в частности, демонстрируется еще одна замечательная возможность современных ассемблеров - использование выражений для вычисления значений операнда, которые можно записывать на месте операнда. Такая возможность использует обычные обозначения арифметических операций, но, по существу требует, чтобы все компоненты такого выражения были определены еще на этапе компиляции программ. Следует отметить, что компоненты таких выражений должны быть заданы явными константами, в частности, определенными через директивы EQU.

Кроме данных выше основных форм записи операндов в индексном способе адресации возможно также применение записи [имя_области + смещение + индексный_регистр], два первых члена которой на этапе компиляции превращаются в одно числовое смещение от начала сегмента данных, сводясь тем самым ко второй из записанных в начале разделов основных форм. (Внутреннее представление этого способа адресации в машинных кодах и есть машинная форма записи операнда [смещение_от_начала_сегмента + индексный_регистр].)

Соседние файлы в предмете Системное программное обеспечение