Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Системное программное обеспечение. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
15.08.2026
Размер:
856 Кб
Скачать

должны быть заданы явными константами, в частности определенными через директивы EQU.

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

ние_от_начала_сегмента + индексный_регистр].)

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

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

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

struct doca { char sex; int age;

char name[10]; };

struct doca persons[20];

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

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

80

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

;struct

doca

sex

DB0

age

DD0

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

81

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

82

Такое введение в использование имен полей 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) является индексно-базо- вый способ. В нем используются указания двух регистров: один содержит базовый адрес какой-то структуры, а другой используется как индексный для доступа к различным элементам массива в составе структуры. В о б- щей форме этот способ записывается для операнда в виде

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

83

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

Практическое значение этого способа заключается в обработке массивов данных внутри экземпляров структур. Например, в следующем фрагменте последовательный доступ к байтам поля 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.

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

84

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]