Режимы адресации являются аспектом архитектуры набора инструкций в большинстве конструкций центральных процессоров (ЦП). Различные режимы адресации, которые определены в данной архитектуре набора инструкций, определяют, как инструкции машинного языка в этой архитектуре идентифицируют операнд (ы) каждой инструкции. Режим адресации определяет, как вычислить эффективный адрес памяти операнда, используя информацию, хранящуюся в регистрах и/или константах, содержащихся в машинной инструкции или в другом месте.
В программировании на компьютере режимы адресации в первую очередь интересны тем, кто пишет на языках ассемблера и разработчикам компиляторов . Для связанной концепции см. ортогональный набор инструкций , который касается способности любой инструкции использовать любой режим адресации.
Не существует общепринятых названий для режимов адресации: разные авторы и производители компьютеров могут давать разные названия одному и тому же режиму адресации или одинаковые названия разным режимам адресации. Кроме того, режим адресации, который в одной данной архитектуре рассматривается как один режим адресации, может представлять функциональность, которая в другой архитектуре охватывается двумя или более режимами адресации. Например, некоторые архитектуры компьютеров со сложным набором команд (CISC), такие как Digital Equipment Corporation (DEC) VAX , рассматривают регистры и литеральные или непосредственные константы как просто другой режим адресации. Другие, такие как IBM System/360 и ее последователи, и большинство конструкций компьютеров с сокращенным набором команд (RISC), кодируют эту информацию в инструкции. Таким образом, последние машины имеют три различных кода инструкций для копирования одного регистра в другой, копирования литеральной константы в регистр и копирования содержимого ячейки памяти в регистр, в то время как VAX имеет только одну инструкцию «MOV».
Термин «режим адресации» сам по себе может толковаться по-разному: как «режим вычисления адреса памяти» или «режим доступа к операнду». Согласно первой интерпретации, инструкции, которые не считывают из памяти и не записывают в память (например, «добавление литерала к регистру»), считаются не имеющими «режима адресации». Вторая интерпретация допускает такие машины, как VAX, которые используют биты режима операнда для разрешения регистра или литерального операнда. Только первая интерпретация применима к таким инструкциям, как «загрузить эффективный адрес», которая загружает адрес операнда, а не сам операнд.
Перечисленные ниже режимы адресации делятся на адресацию кода и адресацию данных. Большинство компьютерных архитектур поддерживают это различие, но есть (или были) некоторые архитектуры, которые позволяют использовать (почти) все режимы адресации в любом контексте.
Приведенные ниже инструкции носят исключительно репрезентативный характер и иллюстрируют режимы адресации, и не обязательно отражают мнемонику, используемую каким-либо конкретным компьютером.
Некоторые компьютеры, например, IBM 709 , RCA 3301, [1] не имеют единого поля режима адреса, а вместо этого имеют отдельные поля для косвенной адресации и индексации.
Архитектуры компьютеров сильно различаются по количеству режимов адресации, которые они предоставляют в оборудовании. Есть некоторые преимущества в устранении сложных режимов адресации и использовании только одного или нескольких более простых режимов адресации, даже если это требует нескольких дополнительных инструкций и, возможно, дополнительного регистра. [2] [3] Доказано [4] [5] [6] что гораздо проще проектировать конвейерные ЦП, если единственными доступными режимами адресации являются простые.
Большинство архитектур RISC имеют только около пяти простых режимов адресации, в то время как архитектуры CISC, такие как DEC VAX, имеют более дюжины режимов адресации, некоторые из которых довольно сложны. Архитектура IBM System/360 имеет только четыре режима адресации; еще несколько были добавлены для архитектуры ESA/390 .
Когда есть только несколько режимов адресации, требуемый конкретный режим адресации обычно кодируется в коде инструкции (например, IBM System/360 и последующие версии, большинство RISC). Но когда есть много режимов адресации, в инструкции часто отводится специальное поле для указания режима адресации. DEC VAX допускал несколько операндов памяти почти для всех инструкций и поэтому зарезервировал первые несколько бит каждого спецификатора операнда для указания режима адресации для этого конкретного операнда. Разделение бит спецификатора режима адресации и битов операции кода операции создает ортогональный набор инструкций .
Даже на компьютере со многими режимами адресации измерения реальных программ [7] показывают, что простые режимы адресации, перечисленные ниже, составляют около 90% или более всех используемых режимов адресации. Поскольку большинство таких измерений основано на коде, сгенерированном из языков высокого уровня компиляторами, это в некоторой степени отражает ограничения используемых компиляторов. [8] [7] [9]
Некоторые архитектуры наборов инструкций, такие как Intel x86 и IBM/360 и их последователи, имеют инструкцию загрузки эффективного адреса . [10] [11] Это вычисляет эффективный адрес операнда и загружает его в регистр, не обращаясь к памяти, на которую он ссылается. Это может быть полезно при передаче адреса элемента массива в подпрограмму. Это также может быть умным способом выполнить больше вычислений, чем обычно, в одной инструкции; например, использование такой инструкции с режимом адресации «база+индекс+смещение» (подробно описано ниже) позволяет сложить два регистра и константу вместе в одной инструкции и сохранить результат в третьем регистре.
Ниже показаны некоторые простые режимы адресации для кода. Номенклатура может различаться в зависимости от платформы.
+----+------------------------------+ |перейти| адрес | +----+------------------------------+ (Фактический адрес ПК = адрес)
Эффективным адресом для абсолютного адреса инструкции является сам параметр адреса без каких-либо изменений.
+----+------------------------------+ |переход| смещение | относительный переход +----+------------------------------+ (Эффективный адрес ПК = адрес следующей инструкции + смещение, смещение может быть отрицательным)
Эффективный адрес для адреса инструкции относительно PC — это параметр смещения, добавленный к адресу следующей инструкции. Это смещение обычно имеет знак, чтобы разрешить ссылку на код как до, так и после инструкции. [12]
Это особенно полезно в связи с инструкциями перехода , поскольку типичные переходы осуществляются на соседние инструкции (в языке высокого уровня большинство операторов if или while достаточно короткие). Измерения реальных программ показывают, что смещение в 8 или 10 бит достаточно велико для примерно 90% условных переходов (примерно ±128 или ±512 байт). [13] Для переходов на инструкции, которые не находятся рядом, используются другие режимы адресации.
Еще одним преимуществом адресации относительно ПК является то, что код может быть позиционно-независимым , т.е. его можно загружать в любое место памяти без необходимости корректировки каких-либо адресов.
+-------+-----+ |jumpVia| рег | +-------+-----+ (Фактический адрес ПК = содержимое регистра «reg»)
Эффективный адрес для косвенной инструкции Register — это адрес в указанном регистре. Например, (A7) для доступа к содержимому регистра адреса A7.
Эффект заключается в передаче управления инструкции, адрес которой находится в указанном регистре.
Многие машины RISC, а также CISC IBM System/360 и их последователи имеют инструкции вызова подпрограммы, которые помещают адрес возврата в регистр адреса — для возврата из этого вызова подпрограммы используется режим косвенной адресации через регистр.
+------+ | nop | выполнить следующую инструкцию +------+ (Эффективный адрес ПК = адрес следующей инструкции)
После выполнения последовательной инструкции процессор немедленно выполняет следующую инструкцию.
На некоторых компьютерах последовательное выполнение не считается режимом адресации.
Большинство инструкций на большинстве архитектур ЦП являются последовательными инструкциями. Поскольку большинство инструкций являются последовательными инструкциями, разработчики ЦП часто добавляют функции, которые намеренно жертвуют производительностью других инструкций — инструкций ветвления — чтобы заставить эти последовательные инструкции выполняться быстрее.
Условные переходы загружают ПК одним из двух возможных результатов в зависимости от условия — большинство архитектур ЦП используют другой режим адресации для «принятой» ветви и последовательное выполнение для «непринятой» ветви.
Многие функции современных процессоров — предварительная выборка инструкций и более сложная конвейеризация , нестандартное выполнение и т. д. — создают иллюзию того, что каждая инструкция завершается до начала следующей, давая те же самые конечные результаты, хотя на самом деле это не совсем то, что происходит внутри.
Каждый « базовый блок » таких последовательных инструкций демонстрирует как временную, так и пространственную локальность референции .
Процессоры, которые не используют последовательное выполнение с программным счетчиком, встречаются крайне редко. В некоторых процессорах каждая инструкция всегда указывает адрес следующей инструкции. Такие процессоры имеют указатель инструкций, который содержит указанный адрес; это не программный счетчик, потому что нет возможности его увеличения. К таким процессорам относятся некоторые компьютеры с барабанной памятью , такие как IBM 650 , SECD machine , Librascope RPC 4000 и RTX 32P. [14]
На процессорах, реализованных с горизонтальным микрокодом , микроинструкция может содержать старшие биты адреса следующей инструкции.
Другие вычислительные архитектуры идут гораздо дальше, пытаясь обойти узкое место фон Неймана, используя различные альтернативы счетчику команд .
Некоторые компьютерные архитектуры имеют условные инструкции (например, ARM , но больше не для всех инструкций в 64-битном режиме) или условные инструкции загрузки (например, x86), которые в некоторых случаях могут сделать условные переходы ненужными и избежать очистки конвейера инструкций . Такая инструкция, как «сравнение», используется для установки кода условия , а последующие инструкции включают проверку этого кода условия, чтобы увидеть, соблюдаются ли они или игнорируются.
+------+-----+-----+ |skipEQ| reg1| reg2| пропустить следующую инструкцию, если reg1=reg2 +------+-----+-----+ (Эффективный адрес ПК = адрес следующей инструкции + 1)
Адресация пропуска может считаться особым видом режима адресации относительно ПК с фиксированным смещением "+1". Как и в случае адресации относительно ПК, некоторые ЦП имеют версии этого режима адресации, которые ссылаются только на один регистр ("skip if reg1=0") или не ссылаются ни на один регистр, неявно ссылаясь на некоторый ранее установленный бит в регистре состояния . Другие ЦП имеют версию, которая выбирает определенный бит в определенном байте для проверки ("skip if bit 7 of reg12 is 0").
В отличие от всех других условных переходов, инструкция «пропустить» никогда не требует очистки конвейера инструкций , хотя может потребоваться игнорирование следующей инструкции.
Ниже показаны некоторые простые режимы адресации данных. Номенклатура может различаться в зависимости от платформы.
+------+-----+-----+-----+ | мул | рег1| рег2| рег3| reg1 := reg2 * reg3; +------+-----+-----+-----+
Этот «режим адресации» не имеет эффективного адреса и не считается режимом адресации на некоторых компьютерах.
В этом примере все операнды находятся в регистрах, а результат помещается в регистр.
Иногда это называют «база плюс смещение».
+------+-----+-----+----------------+ | загрузка | reg | база| смещение | reg := RAM[база + смещение] +------+-----+-----+----------------+ (Эффективный адрес = смещение + содержимое указанного базового регистра)
Смещение обычно представляет собой 16-битное значение со знаком (хотя в 80386 оно было расширено до 32 бит).
Если смещение равно нулю, это становится примером косвенной адресации регистра; эффективный адрес — это просто значение в базовом регистре.
На многих RISC-машинах регистр 0 зафиксирован на значении ноль. Если регистр 0 используется как базовый регистр, это становится примером абсолютной адресации . Однако доступ возможен только к небольшой части памяти (64 килобайта , если смещение составляет 16 бит).
16-битное смещение может показаться очень маленьким по сравнению с размером памяти современных компьютеров (именно поэтому 80386 расширил его до 32-битного). Могло быть и хуже: мэйнфреймы IBM System/360 имеют только беззнаковое 12-битное смещение. Однако принцип локальности ссылок применим: в течение короткого промежутка времени большинство элементов данных, к которым программа хочет получить доступ, находятся довольно близко друг к другу.
Этот режим адресации тесно связан с индексированным абсолютным режимом адресации.
Пример 1 : Внутри подпрограммы программист будет в основном интересоваться параметрами и локальными переменными, которые редко превышают 64 КБ , для которых достаточно одного базового регистра ( указателя кадра ). Если эта подпрограмма является методом класса в объектно-ориентированном языке, то необходим второй базовый регистр, который указывает на атрибуты текущего объекта ( this или self в некоторых языках высокого уровня).
Пример 2 : Если базовый регистр содержит адрес составного типа (записи или структуры), смещение можно использовать для выбора поля из этой записи (большинство записей/структур имеют размер менее 32 КБ).
+------+-----+-----+----------------+ | добавить | reg1| reg2| константа | reg1 := reg2 + константа; +------+-----+-----+----------------+
Этот «режим адресации» не имеет эффективного адреса и не считается режимом адресации на некоторых компьютерах.
Константа может быть знаковой или беззнаковой. Например, move.l #$FEEDABBA, D0
для перемещения непосредственного шестнадцатеричного значения "FEEDABBA" в регистр D0.
Вместо использования операнда из памяти, значение операнда хранится в самой инструкции. На машине DEC VAX литеральные размеры операнда могли быть длиной 6, 8, 16 или 32 бита.
Эндрю Таненбаум показал, что 98% всех констант в программе умещаются в 13 бит (см. Философию проектирования RISC ).
+-----------------+ | очистить бит переноса | +-----------------+ +-------------------+ | очистить аккумулятор | +-------------------+
Неявный режим адресации, также называемый неявным режимом адресации ( язык ассемблера x86 ), не указывает явно эффективный адрес ни для источника, ни для назначения (или иногда для обоих).
В коде операции подразумевается либо эффективный адрес источника (если таковой имеется), либо эффективный адрес назначения (иногда оба).
Неявная адресация была довольно распространена на старых компьютерах (до середины 1970-х годов). Такие компьютеры обычно имели только один регистр, в котором могла выполняться арифметика — аккумулятор. Такие машины-аккумуляторы неявно ссылаются на этот аккумулятор почти в каждой инструкции. Например, операция < a := b + c; > может быть выполнена с помощью последовательности < load b; add c; store a; > — назначение (аккумулятор) подразумевается в каждой инструкции «load» и «add»; источник (аккумулятор) подразумевается в каждой инструкции «store».
Более поздние компьютеры, как правило, имели более одного регистра общего назначения или ячейки оперативной памяти, которые могли быть источником или местом назначения, или и тем, и другим для арифметики, поэтому более поздним компьютерам требовался какой-то другой режим адресации для указания источника и места назначения арифметики.
Среди инструкций x86 некоторые используют неявные регистры для одного из операндов или результатов (умножение, деление, подсчет условного перехода).
Во многих компьютерах (например, x86 и AVR) есть один специальный регистр, называемый указателем стека , который неявно увеличивается или уменьшается при загрузке или извлечении данных из стека, а исходный или целевой эффективный адрес (неявно) является адресом, хранящимся в этом указателе стека.
Многие 32-разрядные компьютеры (например, 68000, ARM или PowerPC) имеют более одного регистра, который можно использовать в качестве указателя стека, и поэтому используют режим адресации «косвенный автоинкремент регистра», чтобы указать, какой из этих регистров следует использовать при загрузке или извлечении данных из стека.
Некоторые современные компьютерные архитектуры (например, IBM/390 и Intel Pentium) содержат некоторые инструкции с неявными операндами для поддержания обратной совместимости с более ранними разработками.
На многих компьютерах инструкции, которые переключают бит пользовательского/системного режима, бит разрешения прерывания и т. д., неявно указывают специальный регистр, который содержит эти биты. Это упрощает оборудование, необходимое для перехвата этих инструкций, чтобы соответствовать требованиям виртуализации Попека и Голдберга — в такой системе логике перехвата не нужно смотреть на какой-либо операнд (или на конечный эффективный адрес), а только на код операции.
Было разработано несколько процессоров, в которых каждый операнд всегда неявно указан в каждой инструкции — процессоры с нулевыми операндами .
+------+-----+------------------------------------ --+ | загрузка | рег | адрес | +------+-----+------------------------------------ --+ (Фактический адрес = адрес, указанный в инструкции)
Это требует места в инструкции для довольно большого адреса. Это часто доступно на машинах CISC, которые имеют инструкции переменной длины, такие как x86 .
Некоторые машины RISC имеют специальную инструкцию Load Upper Literal , которая помещает 16- или 20-битную константу в верхнюю половину регистра. Затем ее можно использовать в качестве базового регистра в режиме адресации base-plus-offset, который предоставляет младшие 16 или 12 бит. Такая комбинация позволяет получить полный 32-битный адрес.
+------+-----+-----+------------------------------ --+ | загрузка | рег |индекс| адрес | +------+-----+-----+------------------------------ --+ (Фактический адрес = адрес + содержимое указанного индексного регистра)
Это также требует места в инструкции для довольно большого адреса. Адрес может быть началом массива или вектора, а индекс может выбирать конкретный требуемый элемент массива. Процессор может масштабировать индексный регистр, чтобы учесть размер каждого элемента массива .
Обратите внимание, что это более или менее то же самое, что и режим адресации «база плюс смещение», за исключением того, что смещение в этом случае достаточно велико для адресации любой ячейки памяти.
Пример 1 : Внутри подпрограммы программист может определить строку как локальную константу или статическую переменную . Адрес строки хранится в литеральном адресе в инструкции. Смещение — какой символ строки использовать в этой итерации цикла — хранится в индексном регистре.
Пример 2 : Программист может определить несколько больших массивов как глобальные или как переменные класса . Начало массива хранится в буквальном адресе (возможно, измененном во время загрузки программы перемещающим загрузчиком ) инструкции, которая ссылается на него. Смещение — какой элемент из массива использовать на этой итерации цикла — хранится в индексном регистре. Часто инструкции в цикле повторно используют один и тот же регистр для счетчика цикла и смещений нескольких массивов.
+------+-----+-----+-----+ | загрузка | рег | база|индекс| +------+-----+-----+-----+ (Эффективный адрес = содержимое указанного базового регистра + содержимое указанного индексного регистра)
Базовый регистр может содержать начальный адрес массива или вектора, а индекс может выбирать конкретный требуемый элемент массива. Процессор может масштабировать индексный регистр, чтобы учесть размер каждого элемента массива . Это может использоваться для доступа к элементам массива, переданного в качестве параметра.
+------+-----+-----+-----+----------------+ | загрузка | рег | база|индекс| смещение | +------+-----+-----+-----+----------------+ (Эффективный адрес = смещение + содержимое указанного базового регистра + содержимое указанного индексного регистра)
Базовый регистр может содержать начальный адрес массива или вектора записей, индекс может выбирать конкретную требуемую запись, а смещение может выбирать поле в этой записи. Процессор может масштабировать индексный регистр, чтобы учесть размер каждого элемента массива .
+------+-----+-----+-----+ | загрузка | рег | база|индекс| +------+-----+-----+-----+ (Эффективный адрес = содержимое указанного базового регистра + масштабированное содержимое указанного индексного регистра)
Базовый регистр может содержать начальный адрес массива или векторной структуры данных , а индекс может содержать смещение одного конкретного требуемого элемента массива.
Этот режим адресации динамически масштабирует значение в индексном регистре, чтобы учесть размер каждого элемента массива, например, если элементы массива являются числами с плавающей точкой двойной точности, занимающими 8 байт каждый, то значение в индексном регистре умножается на 8 перед использованием в вычислении эффективного адреса. Коэффициент масштабирования обычно ограничен степенью двойки , так что можно использовать сдвиг , а не умножение.
+------+------+-----+ | загрузка | рег1 | база| +------+------+-----+ (Фактический адрес = содержимое базового регистра)
Некоторые компьютеры используют это как отдельный режим адресации. Многие компьютеры просто используют базу плюс смещение со значением смещения 0. Например, (A7)
+------+-----+-------+ | загрузка | рег | база | +------+-----+-------+ (Фактический адрес = содержимое базового регистра)
После определения эффективного адреса значение в базовом регистре увеличивается на размер элемента данных, к которому необходимо получить доступ. Например, (A7)+ получит доступ к содержимому регистра адреса A7, а затем увеличит указатель адреса A7 на 1 (обычно на 1 слово). В цикле этот режим адресации можно использовать для пошагового прохождения по всем элементам массива или вектора.
В языках высокого уровня часто считается хорошей идеей, что функции, возвращающие результат, не должны иметь побочных эффектов (отсутствие побочных эффектов значительно облегчает понимание и проверку программы). Этот режим адресации имеет побочный эффект в том, что изменяется базовый регистр. Если последующий доступ к памяти вызывает ошибку (например, ошибку страницы, ошибку шины, ошибку адреса), приводящую к прерыванию, то перезапуск инструкции становится гораздо более проблематичным, поскольку один или несколько регистров, возможно, придется вернуть в состояние, в котором они были до первоначального запуска инструкции.
По крайней мере, две компьютерные архитектуры имели проблемы с реализацией восстановления после прерываний при использовании этого режима адресации:
+------+-----+-----+ | загрузка | рег | база| +------+-----+-----+ (Фактический адрес = новое содержимое базового регистра)
Перед определением эффективного адреса значение в базовом регистре уменьшается на размер элемента данных, к которому необходимо получить доступ.
В цикле этот режим адресации может использоваться для перехода назад по всем элементам массива или вектора. Стек может быть реализован с помощью этого режима в сочетании с предыдущим режимом адресации (автоинкремент).
См. обсуждение побочных эффектов в режиме автоинкрементной адресации.
Любой из режимов адресации, упомянутых в этой статье, может иметь дополнительный бит для указания косвенной адресации, т. е. адрес, вычисленный с использованием некоторого режима, на самом деле является адресом местоположения (обычно полного слова ), которое содержит фактический эффективный адрес.
Косвенная адресация может использоваться для кода или данных. Она может значительно упростить реализацию указателей , ссылок или дескрипторов , а также может облегчить вызов подпрограмм, которые в противном случае не адресуются. Косвенная адресация приводит к снижению производительности из-за дополнительного доступа к памяти.
Некоторые ранние миникомпьютеры (например, DEC PDP-8 , Data General Nova ) имели всего несколько регистров и ограниченный диапазон прямой адресации (8 бит). Поэтому использование косвенной адресации памяти было почти единственным способом обращения к сколько-нибудь значительному объему памяти.
Половина из восьми режимов адресации DEC PDP-11 являются отложенными. Регистровый отложенный @Rn такой же, как и регистровый косвенный, как определено выше. Режимы преддекрементного отложенного @-(Rn), постинкрементного отложенного @(Rn)+ и индексированного отложенного @nn(Rn) указывают на адреса в памяти, которые считываются для поиска адреса параметра. Отложенные режимы PDP-11 в сочетании со счетчиком программ обеспечивают его абсолютный и относительный к ПК режимы адресации.
+------+------+---------+----------------+ | загрузка | reg1 | база=PC | смещение | +------+------+---------+----------------+ reg1 := RAM[ПК + смещение] (Фактический адрес = ПК + смещение)
Режим адресации относительно ПК может использоваться для загрузки регистра со значением, хранящимся в памяти программ на небольшом расстоянии от текущей инструкции. Его можно рассматривать как особый случай режима адресации "база плюс смещение", который выбирает счетчик программ (ПК) в качестве "базового регистра".
Есть несколько процессоров, которые поддерживают ссылки на данные, относящиеся к ПК. К таким процессорам относятся:
Архитектура x86-64 и 64-битная архитектура ARMv8-A [15] имеют режимы адресации относительно ПК, называемые «RIP-relative» в x86-64 и «literal» в ARMv8-A. Motorola 6809 также поддерживает режим адресации относительно ПК.
Архитектура PDP-11 , архитектура VAX и 32-разрядная архитектура ARM поддерживают адресацию относительно ПК, имея ПК в регистровом файле.
Архитектура IBM z/Architecture включает в себя специальные инструкции, например, Load Relative Long, с адресацией относительно ПК, если активна функция расширения общих инструкций.
При использовании этого режима адресации компилятор обычно помещает константы в литеральный пул непосредственно перед или сразу после подпрограммы, которая их использует, чтобы предотвратить случайное выполнение этих констант в качестве инструкций.
Этот режим адресации, который всегда извлекает данные из памяти или сохраняет данные в памяти, а затем последовательно переходит к выполнению следующей инструкции (эффективный адрес указывает на данные), не следует путать с «переходом относительно ПК», который не извлекает данные из памяти и не сохраняет их в памяти, а вместо этого переходит к какой-то другой инструкции по заданному смещению (эффективный адрес указывает на исполняемую инструкцию).
Перечисленные здесь режимы адресации использовались в период 1950–1980 годов, но больше не доступны на большинстве современных компьютеров. Этот список ни в коем случае не является полным; время от времени использовались и другие интересные и необычные режимы адресации, например, абсолютный-минус-логический-ИЛИ двух или трех индексных регистров. [16] [17]
Если размер слова больше адреса, то слово, на которое ссылаются для косвенной адресации памяти, может само иметь косвенный флаг, установленный для указания другого косвенного цикла памяти. Этот флаг называется битом косвенности , а результирующий указатель является помеченным указателем , причем бит косвенности помечает, является ли он прямым указателем или косвенным указателем. Необходимо следить за тем, чтобы цепочка косвенных адресов не ссылалась сама на себя; если это так, можно получить бесконечный цикл при попытке разрешения адреса.
IBM 1620 , Data General Nova , HP 2100 series и NAR 2 имеют такую многоуровневую косвенную память и могут входить в такой бесконечный цикл вычисления адреса. Режим косвенной адресации памяти на Nova повлиял на изобретение косвенного потокового кода .
Компьютер DEC PDP-10 с 18-битными адресами и 36-битными словами допускал многоуровневую косвенную адресацию с возможностью использования индексного регистра на каждом этапе. Система приоритетных прерываний запрашивалась перед декодированием каждого адресного слова. [18] Таким образом, косвенный адресный цикл не помешал бы выполнению процедур обслуживания устройств, включая любой обработчик истечения времени квантования упреждающего многозадачного планировщика. Циклическая инструкция будет обрабатываться как любое другое вычислительно-связанное задание.
На некоторых компьютерах были адреса, которые ссылались на регистры, а не на первичное хранилище, или на первичную память, используемую для реализации этих регистров. Хотя на некоторых ранних компьютерах были адреса регистров в верхней части диапазона адресов, например, IBM 650 , [19] [a] IBM 7070 , [20] [c], тенденция заключалась в использовании только адреса регистра в нижней части и использовании только первых 8 или 16 слов памяти (например, ICL 1900 , DEC PDP-10). Это означало, что не было необходимости в отдельной инструкции «добавить регистр к регистру» — можно было просто использовать инструкцию «добавить память к регистру».
В случае ранних моделей PDP-10, не имевших кэш-памяти, жесткий внутренний цикл, загруженный в первые несколько слов памяти (где быстрые регистры были адресуемыми, если они установлены), работал гораздо быстрее, чем это было бы в памяти на магнитных сердечниках.
Более поздние модели серии DEC PDP-11 отображали регистры на адреса в области ввода/вывода, но это было в первую очередь предназначено для обеспечения удаленной диагностики. Сбивая с толку, 16-битные регистры отображались на последовательные 8-битные байтовые адреса.
Миникомпьютер DEC PDP-8 имел восемь специальных ячеек (по адресам с 8 по 15). При доступе через косвенную адресацию памяти эти ячейки автоматически увеличивались перед использованием. [21] Это позволяло легко проходить по памяти в цикле без необходимости использования аккумулятора для увеличения адреса.
Мини-компьютер Data General Nova имел 16 специальных ячеек памяти по адресам с 16 по 31. [22] При доступе через косвенную адресацию памяти ячейки с 16 по 23 автоматически увеличивались перед использованием, а ячейки с 24 по 31 автоматически уменьшались перед использованием.
Процессоры семейства Data General Nova , Motorola 6800 и MOS Technology 6502 имели очень мало внутренних регистров. Арифметические и логические инструкции в основном выполнялись над значениями в памяти, а не над внутренними регистрами. В результате многие инструкции требовали двухбайтового (16-битного) расположения в памяти. Учитывая, что коды операций на этих процессорах имели длину всего один байт (8 бит), адреса памяти могли составлять значительную часть размера кода.
Разработчики этих процессоров включили частичное средство, известное как адресация «нулевой страницы». К начальным 256 байтам памяти ($0000 – $00FF; также известным как страница «0») можно было получить доступ с помощью однобайтового абсолютного или индексированного адреса памяти. Это сокращало время выполнения инструкции на один такт и длину инструкции на один байт. Сохраняя часто используемые данные в этой области, программы можно было сделать меньше и быстрее.
В результате нулевая страница использовалась аналогично регистровому файлу. Однако во многих системах это приводило к высокой загрузке области памяти нулевой страницы операционной системой и пользовательскими программами, что ограничивало ее использование, поскольку свободное пространство было ограничено.
Режим адресации нулевой страницы был улучшен в нескольких поздних моделях 8-разрядных процессоров, включая WDC 65816 , CSG 65CE02 и Motorola 6809. Новый режим, известный как адресация «прямой страницы», добавил возможность перемещения 256-байтового окна памяти нулевой страницы из начала памяти (адрес смещения $0000) в новое место в пределах первых 64 КБ памяти.
CSG 65CE02 позволял перемещать прямую страницу в любую 256-байтовую границу в пределах первых 64 КБ памяти, сохраняя 8-битное значение смещения в новом регистре базовой страницы (B). Motorola 6809 могла делать то же самое со своим регистром прямой страницы (DP). WDC 65816 пошел на шаг дальше и позволял перемещать прямую страницу в любое место в пределах первых 64 КБ памяти, сохраняя 16-битное значение смещения в новом регистре прямой страницы (D).
В результате большее количество программ смогли использовать расширенный режим прямой адресации страниц по сравнению с устаревшими процессорами, которые включали только режим адресации нулевых страниц.
Это похоже на масштабируемую индексную адресацию, за исключением того, что инструкция имеет два дополнительных операнда (обычно константы), а оборудование проверяет, находится ли значение индекса между этими границами.
В другом варианте для хранения границ используются векторные дескрипторы; это упрощает реализацию динамически выделяемых массивов и при этом обеспечивает полную проверку границ.
Некоторые компьютеры имели специальные режимы косвенной адресации для подполей внутри слов.
Косвенное слово адресации символов серии GE /Honeywell 600 задает 6-битные или 9-битные поля символов в своем 36-битном слове.
DEC PDP-10 , также 36-битный, имел специальные инструкции, которые позволяли обрабатывать память как последовательность битовых полей фиксированного размера или байтов любого размера от 1 до 36 бит. Однословный дескриптор последовательности в памяти, называемый «указателем байта», содержал текущий адрес слова в последовательности, позицию бита в слове и размер каждого байта.
Существовали инструкции для загрузки и сохранения байтов через этот дескриптор, а также для увеличения дескриптора для указания на следующий байт (байты не разделялись по границам слов). Большая часть программного обеспечения DEC использовала пять 7-битных байтов на слово (обычные символы ASCII), при этом один бит на слово оставался неиспользованным. Реализации C должны были использовать четыре 9-битных байта на слово, поскольку функция 'malloc' в C предполагает, что размер int является некоторым кратным размеру char ; [ 23] фактическое кратное определяется системно-зависимым оператором времени компиляции sizeof .
Elliott 503 , [24] Elliott 803 , [24] [25] и Apollo Guidance Computer использовали только абсолютную адресацию и не имели никаких индексных регистров. Таким образом, косвенные переходы или переходы через регистры не поддерживались в наборе инструкций. Вместо этого можно было дать указание добавить содержимое текущего слова памяти к следующей инструкции . Добавление небольшого значения к следующей инструкции, которая должна быть выполнена, могло, например, изменить a JUMP 0
на a JUMP 20
, тем самым создавая эффект индексированного перехода. Обратите внимание, что инструкция изменяется на лету и остается неизменной в памяти, т. е. это не самомодифицирующийся код . Если значение, добавляемое к следующей инструкции, было достаточно большим, оно могло изменить код операции этой инструкции, а также или вместо адреса.
*p++
в языке программирования C.*--p
в языке программирования C при операциях заполнения стека .... MIPS-X использует один режим адресации: базовый регистр плюс смещение. Этот простой режим адресации позволяет вычислять эффективный адрес очень рано...
C54x имеет 17 режимов адресации данных, не считая доступа к регистрам, но четыре из MIPS составляют 70% режимов. Автоинкремент и автодекремент, встречающиеся в некоторых архитектурах RISC, составляют еще 25% использования. Эти данные были собраны из измерения статических инструкций для библиотеки C-callable из 54 подпрограмм DSP, закодированных на языке ассемблера.
3 программы, измеренные на машине со всеми режимами адресации (VAX) ... 75% смещения и немедленного
79% всех выполненных инструкций можно заменить инструкциями RISC или синтезировать в инструкции RISC, используя только базовую комбинацию блочных инструкций.
2-9: Расчет эффективного адреса: тест «PI RQ ?»