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

4.3. Базовая и индексно базовая адресации

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

Для пояснения существа использования базовой адресации будем исходить из следующего описания на языке Си:

struct doca {

char sex;

int age;

char name[10];

};

struct doca persons[20];

которое в упрощенном варианте подготавливает массив структур данных для учетной информации о некоторых людях (пол, возраст и имя).

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

Если отдельно описать строение данной структуры на ассемблере, мы получим следующее:

; struct doca

sex DB 0

age DD 0

name TIMES 10 DB 0

Простейшее решение заключается в использовании численных смещений от начала структуры. Непосредственно видно (в том числе из листинга соответствующей программы), что поле sex находится с нулевым смещением от начала экземпляра структуры, поле age - на расстоянии одного байта от начала экземпляра структуры, а поле name, соответственно, на расстоянии пяти байтов от начала структуры (считая, что данные типа int требуют для записи в 32-битной архитектуре четырех байтов).

Технической и, в некоторой степени, языковой проблемой для ассемблера является то, что эти поля нужно обозначать и использовать для любого из экземпляров в массиве структур. Базовый способ адресации и позволяет тут же решить эту задачу. Предварительно в некоторый регистр, называемый далее базовым в операнде с рассматриваемой адресацией, заносится значение адреса экземпляра структуры. Тогда обозначение [базовый_регистр+0] задает в операнде команды поле sex, обозначение [базовый_регистр+1] задает поле age, а обозначение [базовый_регистр+5] задает поле name. (С помощью последнего обозначения можно добраться до одного, двух или четырех начальных байтов поля name, используя, соответственно, модификаторы byte, word и dword.) Меняя значение в регистре базовый_регистр, можно с помощью одной и той же команды добираться до одноименного поля в различных экземплярах структуры.

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

Например, для вычисления суммы значений полей age в предложенном выше примере (для вычисления среднего возраста или чего-то подобного) можно использовать следующий фрагмент программы на ассемблере:

mov ebx, persons ; адрес массива структур заносится в ebx

mov ecx, 20

mov eax, 0 ; регистр EAX предназначен для вычисляемой суммы

povt: add eax, [ebx+1] ; прибавление значения поля age

add ebx, 15 ; увеличение регистра ebx на размер структуры doca

loop povt

Здесь в начале значение регистра ebx устанавливается, чтобы указывать на начало области массива структур, а затем внутри цикла каждый раз увеличивается на длину экземпляра структуры, выраженную в байтах, тем самым указывая далее на начало следующего элемента структуры в массиве. Операнд [ebx+1] в команде сложения всегда поэтому задает поле age описанной выше структуры данных.

Для описания всего массива данных может быть использована "очень слепая" форма записи в виде

persons TIMES 20*15 db 0

или же более развернутая для программиста форма, применяющая директиву повторения REP

persons

%rep 20

DB 0

DD 0

TIMES 10 DB 0

%endrep

Эта директива относится к средствам предпроцессора (предварительной до собственно компилятора обработки исходного текста). Она с помощью начальной части конструкции %rep номер задает число повторений идущего далее - до строки с ключевым словом %endrep - текста. В данном случае 20 раз повторяется описание полей для структуры.

Более мощным средством являются предпроцессорные директивы описания структуры данных. Они задаются ключевыми словами STRUC и ENDSTRUC, указывающими начало и конец описания структуры, причем имя структуры задается как единственный параметр в директиве STRUC. Само описание при этом должно задаваться исключительно резервированием памяти. В нашем примере мы получаем

struc doca

sex resb 1

age resd 1

name resb 10

endstruc

Такое введение в использование имен полей sex, age, name равносильно явному заданию для каждого из них числового значения, равного смещению соответствующего поля относительно начала структуры. В данном случае неявно для поля sex задается значение 0, для поля age - значение 1, для поля name - значение 5. После этого можно в операндах, указывающих доступ к этим полям записывать, соответственно, [ebx+sex], [ebx+age], [ebx+name],

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

struc doca

.sex resb 1

.age resd 1

.name resb 10

endstruc

то имена .sex, .age, .name будут относиться только к структуре doca. Определенные таким образом имена полей должны использоваться вместе с именем структуры в виде имя_структуры.имя_поля. Все это сделано, чтобы можно было применять одноименные поля в различных структурах данных, которые различаются именно по квалификатору имени структуры, стоящему перед именем поля.

В последнем примере обозначение поля sex в операнде, который в качестве базового использует регистр ebx, должно записываться в виде [ebx+doca.sex], использование поля age - в виде [ebx+doca.age], а поля name - в виде [ebx+doca.name]. Еще раз подчеркнем, что вместо таких достаточно наглядных, но более длинных обозначений программист может использовать просто числовое значение смещения.

Еще более сложным способом адресации (и наиболее сложным в базовой 16-битной архитектуре процессоров Intel) является индексно базовый способ. В нем используются указания двух регистров: один содержит базовый адрес какой-то структуры, а другой используется как индексный для доступа к различным элементам массива в составе структуры. В общей форме этот способ записывается для операнда в виде

[базовый_регистр+индексный_регистр+смещение]

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

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

mov ebx, persons ; адрес массива структур заносится в ebx

mov ecx, 20

povt: mov esi, 0 ; нулевой индекс в esi для доступа к нач. байту области

iname: . . . использование байтов области name

; . . . с помощью операнда в виде [ebx+esi+5]

inc esi ; esi переустановить на след. элемент в массиве name

cmp esi, 10

jl iname

add ebx, 15 ; увеличение регистра ebx на размер структуры doca

loop povt

Здесь, как уже указывалось выше, обозначение доступа к байту в массиве name может быть записано в виде [ebx+esi+doca.name], но только, если в программе директивой предпроцессора определено строение структуры doca.

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

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