PersCom — Компьютерная Энциклопедия Компьютерная Энциклопедия

Процессор

Способы адресации при адресной организации памяти

Понятие косвенной адресации

Пусть какой-нибудь способ адресации (1) указывает место положения операнда (неважно, регистр процессора или адрес в памяти). Можно представить себе другой способ адресации (2), во всем аналогичный способу (1) за исключением того, что в указываемом месте расположен не сам операнд, а его адрес, т.е. номер ячейки в ОЗУ, где находится операнд. Тогда будем говорить, что способ (1) — прямой, а соответствующий ему способ (2) — косвенный по отношению к способу (1). В символике языков ассемблера для обозначения косвенности используются скобки или символ @.


1) add ax,loc — эта ассемблерная запись означает "прибавить к содержимому регистра AX содержимое ячейки памяти, адрес которой обозначен символическим именем LOC”.

2) ADD AX,(LOC)или ADD AX,@LOC — в этой записи используется косвенная адресация, запись означает "прибавить к содержимому регистра AX содержимое ячейки памяти, адрес которой хранится в ячейке памяти с символическим именем LOC”.


Можно провести аналогию между использованием косвенной адресации в языке ассемблера и использованием указателей в языке Си. В строке iA+ = iB ; обращение к операнду iB произойдет с использованием прямой адресации. Строка iA+ = *piB; использует косвенную адресацию переменной через указатель piB = &iB. По индукции можно представить себе двойную, тройную косвенность и т.п. Существовали компьютеры, в которых была реализована косвенность произвольной глубины. Рассмотрим теперь конкретно различные способы адресации. При рассмотрении использованы мнемоники ассемблера для процессоров i*86. Используемый в команде способ адресации кодируется в адресном поле операнда. За исключением непосредственной и абсолютной адресации, адресное поле указывает на адресный регистр (может быть на несколько) и задает способ вычисления адреса с участием содержимого этого регистра (ов).

Неявная (inherent) адресация

Этот термин относится не к способу вычисления адреса (местоположения) операнда, а к способу обозначения этого местоположения в синтаксисе ассемблера. Например, команда "поместить в стек”: push ax.

Никаких вычислений для определения адреса операнда делать не надо, операнд выбирается из ОЗУ вслед за командой. Операнд может быть разной длины (занимать разное число ячеек/байтов).

Абсолютная или прямая адресация

В команде за КОП помещается заранее известный адрес операнда. Обратите внимание, что абсолютная адресация является косвенным вариантом для непосредственной адресации. add cx, [123] ; содержимое регистра складывается с содержимым ячейки, абсолютный адрес которой входит в состав команды (см. рисунок).

Для выборки операнда нужно дополнительное обращение к ОЗУ.

Регистровая адресация

Операнд находится в одном из регистров процессора. sub bx, si ; вычитаются два операнда, находящиеся в регистрах процессора (см. рисунок ниже).

Обращение к регистру процессора гораздо быстрее, чем к ячейке ОЗУ. Код регистра занимает более короткое поле в команде, чем операнд или адрес.

Косвенно-регистровая адресация

Адрес операнда находится в одном из регистров процессора. Во многих процессорах регистры специализированы, и адрес может находиться не в любом из них (см. рисунок ниже).
mov [si], 12

Указатель регистра Ri занимает более короткое поле чем адрес. Тот факт, что адрес операнда находится в регистре, позволяет вычислять или модифицировать этот адрес, при этом один и тот же участок программы может обрабатывать разные элементы данных (находящиеся в разных адресах).
Вот фрагмент, суммирующий в регистре ax элементы массива слов:
mov si, "начальный адрес массива"
mov cx, "количество элементов массива"
ckl add ax, [si]; прибавляем следующий элемент
add si, 2; модифицируем адрес в массиве
loop ckl; организуем цикл
Выделенные команды эквивлентны Си-фрагменту sum += *(piMas++); .

Автоинкрементная (автодекрементная) адресация

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

В ходе выполнения команды с данным типом адресации после (либо до) выборки операнда из ОЗУ содержимое регистра Ri модифицируется: к его старому содержимому прибавляется число L — длина операнда в байтах (в минимальных адресуемых единицах). Таким образом после этой модификации в Ri оказывается адрес следующего элемента данных. Автоинкрементная адресация позволяет обращаться к элементам данных, расположенных в памяти подряд по возрастанию адресов (например, к элементам массива). При автодекрементной адресации сложение с L заменяется на вычитание, и элементы данных перебираются в порядке убывания их адресов (см. рисунок ниже).

Величина L, на которую происходит увеличение или уменьшение адреса, в простейшем случае равна минимальной адресуемой единице (байту). Однако, если процессор поддерживает операции с операндами разной длины (байт, слово, двойное слово,...), то и автоиндексация/ декремент может быть реализован на 1, на 2, на 4, ...

Если модификация адресного регистра происходит после обращения к операнду, такую разновидность называют постинкрементной адресацией, если модификация адреса выполняется перед обращением к операнду — преинкрементной. Наиболее часто в процессоре реализуется сочетание постинкрементной и предекрементной адресации. В процессорах i*86 автоиндексная адресация в общем виде (т.е. для использования в произвольной команде) не реализована. Однако в неявном виде она использована в командах операций со строками. Например, при выполнении команды LODS происходит загрузка в регистр AL (или AX или EAX) содержимого ячейки памяти, на которую указывает адресный регистр SI, после чего содержимое регистра SI автоматически модифицируется.

Многокомпонентные способы формирования адреса

Многокомпонентное формирование адреса тесно связаны с идеей относительной адресации. Если отсчитывать адреса объектов программы от места, жестко привязанного к программе (например, от ее начала), то эти относительные значения не меняются, куда бы ни была загружена программа. То же можно сказать и про любую часть программы (например, про участок памяти с данными). Как же можно осуществить такую относительную адресацию?
Для этого можно формировать адрес из двух слагаемых:


•Одно (базовый адрес) зависит от того, куда загружаем программу, задается перед загрузкой, и в течение всего времени выполнения программы остается неизменным (но от загрузки к загрузке может изменяться).


•Второе (относительный адрес) представляет собой разность базового адреса и абсолютного адреса объекта. Адрес задается не как абсолютное значение, а как смещение относительно какого-либо базового значения.


Хочется обеспечить позиционную независимость (без пересчета адресных частей команд). Если вспомним, что после трансляции загружаемый (двоичный) образ программы не меняется, можем высказать идею отсчитывать адреса относительно чего-то в самой программе. Идея формировать адрес как комбинацию (сумму или конкатенацию) нескольких компонент используется как в способах адресации, так и при трансляции адресов. Между понятиями "способ адресации" и "процедура трансляции адреса" непросто провести более-менее четкую границу. Та часть преобразования адресной информации, которая изменяется от одной команды к другой — способ адресации. Трансляция адреса — часть преобразования адреса, одинаковая для разных команд. Трансляцией адреса тоже можно управлять (например, включить или выключить трансляцию страниц), однако это переключение выполняется редко, после чего значительная часть программы выполняется в заданном единожды режиме.

Многокомпонентные способы адресации

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


•а) При вычислении адреса элемента в сложной структуре данных часть действий по этому вычислению можно возложить на адресную арифметику. Например, требуется определить адрес элемента двумерного массива с индексами i, j, если начальный адрес массива AddrM, длина строки массива LStr, а длина одного элемента LElm. Формула для вычисления адреса имеет вид:
Addr(i,j) = AddrM + LStr * (i-1) * LElm + (j-1) * LElm
При использовании многокомпонентной адресации, использующей три компоненты (например, базово-индексной адресации со смещением в процессорах i*86) с компонентами можно связывать адрес начала массива, смещение в массиве от начала до нужной строки и смещение в строке до нужного элемента. Сложение компонент выполнит автоматически адресная арифметика.

•б) Компонента адреса, хранящаяся в регистре или в команде, может быть короче полного адреса (и, значит, занимать меньше места). Это позволит адресовать более коротким полем память большего объема (см. например страничную адресацию).


•в) Возможно в любой момент перемещение в памяти блока объектов с одновременным изменением содержимого базового регистра, участвующего в формировании всех адресов при доступе к этим объектам..


•г) Использование в качестве адресной компоненты счетчика команд автоматически дает позиционную независимость (статическую и динамическую перемещаемость).

Страничная адресация

Это, пожалуй, простейший из многокомпонентных способов. Адрес разбивается на две части, которые объединяются не сложением, а конкатенацией (соединением двух частей числа). Старшая часть адреса указывает номер страницы. Она либо хранится в специальном регистре страницы (общий случай), либо берется из счетчика команд (адресация на текущую страницу), либо фиксирована (часто так делается адресация на нулевую страницу, которая используется для специальных целей). В команде (или в регистре) указывается только младшая часть адреса. Таким образом удается уменьшить длину команды.

Относительная адресация

В качестве одной из компонент при формировании адреса используется счетчик команд. При этом способе адресации операнд отстоит в памяти от команды на фиксированную величину. Иными словами, операнд указывается путем задания его смещения (displacement) в памяти относительно обращающейся к операнду команды. Использование только относительной адресации делает программы позиционно- независимыми, т.е. их можно перемещать в памяти без каких бы то ни было изменений в тексте программы. Относительная адресация используется во многих процессорах в командах условного ветвления, причем чаще всего смещение имеет формат "байт со знаком" и способно задать переход в диапазоне +127 -128 байтов.

Стековый доступ к памяти

Стековый доступ к памяти происходит в большинстве процессоров в следующих ситуациях:
1) При выполнении команд стекового доступа: "поместить в стек" pushили "извлечь из стека" pop.
2) При выполнении команды вызова подпрограммы и при возврате из нее.
3) При входе в прерывание и при возврате из прерывания.


Положение стека в адресуемой памяти определяется содержимым указателя стека. Поскольку указатель стека программно доступен, программист может задать его значение обычной командой пересылки. Например, команда mov sp,#1000h задает положение стека, начиная с адреса 1000h. При стековом доступе содержимое указателя стека используется как адрес операнда-приемника при записи в стек или как адрес операнда- источника при считывании из стека. При обращении к стеку автоматически модифицируется и содержимое указателя стека, чтобы обеспечить следующее обращение к очередной ячейке стека. Используя ранее введенную терминологию, можно сказать, что обращение к стеку происходит с использованием косвенно-регистровой адресации через указатель стека с автоиндексацией (см. таблицу ниже). В разных процессорах стековый доступ может быть реализован по-разному в нескольких аспектах:

1. Направление роста стека. Если при записи в стек, содержимое указателя стека автоматически увеличивается (и, соответственно, при считывании автоматически уменьшается), то говорят, что стек растет в сторону увеличения адресов. В противоположном случае говорят, что стек растет в сторону уменьшения адресов.
2. Если модификация указателя стека выполняется до записи и соответственно после считывания, то указатель стека всегда указывает на последнюю занятую ячейку стека. Наоборот, если модификация производится после записи и до считывания, указатель стека всегда указывает на первую свободную ячейку стека.

Если запись в стек происходит с преиндексацией, то считывание должно происходить с постиндексацией (и наоборот). Распространение различных видов адресации (см. таблицу ниже) зависит от типа АСК. Достаточно ясна ситуация с RISC архитектурой. Из самой идеи подхода вытекает преимущественный способ адресации: регистровая. Для аккумуляторной архитектуры главные способы адресации — прямая и непосредственная. В таблице показана частота применения разных способов адресации на двух тестовых программах для процессоров типа Intel 80x86. Видно, что наиболее активно используется прямая и базово-регистровая адресации, хотя интенсивность использования различных способов тесно связана с решаемой задачей.