Э. Таненбаум - Архитектура компьютера (1127755), страница 101
Текст из файла (страница 101)
Именно это и сообщает ассемблеру знак 11. Сходным образом третья команда помещает в КЗ первое слово после массива. Интересно отметить, что само тело цикла не содерзкит каких-либо адресов памяти. В четвертой команде используются регистровая и косвенная адресация. В пятой команде применяются регистровая и непосредственная адресация, в шестой — оба раза регистровая. Команда В1.Т могла бы использовать адрес памяти, однако более привлекательным является определение адреса с помощью 8-разрядного смещения, связанного с самой командой В~Т. Таким образом, вообтце без обращения по адресам памяти, мы получили короткий и быстрый цикл.
Кстати, эта программа предназначена для РепЦшп 4, только мы переименовали команды и регистры и для простоты изменили запись. Теоретически есть еще один способ выполнения этого фрагмента без косвенной регистровой адресации. Цикл мог бы содержать команду для прибавления А к регистру К1, например: ЯОО Д1. Я При косвенной регистровой адресации искомый операнд берется из памяти или отправляется в память, но адрес не фиксируется жестко в команде, как при прямой адресации, а находится в регистре.
Если адрес используется таким образом, он называется указателем. Преимутцество косвенной адресации состоит в том, что можно обращаться к памяти, не имея в команде полного адреса. Кроме того, многократно выполняя данную команду, можно, меняя значение в регистре, использовать разные слова памяти. Чтобы понять, почему может быть полезно использовать разные слова при каждом выполнении команды, представим себе цикл, который проходит по 1024-элементному одномерному массиву целых чисел для получения в регистре К1 суммы элементов. Вне этого цикла какой-то другой регистр, например К2, может указывать на первый элемент массива, а еще один регистр, например КЗ, — на первый адрес после массива.
Массив содержит 1024 целых числа по 4 байта каждое. Если массив начинается с элемента А, то первый адрес после массива будет А ч- 4098, Типичная программа на ассемблере, выполняющая это вычисление для двухадресной машины, показана в листинге 5.1. Адресация 407 Тогда при каждом шаге команла должна увеличиваться на 4. Таким образом, после одного шага команда будет выглядеть следующим образом; И далее аналогично до завершения цикла. Программа, которая сама изменяет себя подобным образом, называется самомодифицирующейся программой. Идея, предложенная еще Джоном фон Нейманом, применялась в старых компьютерах, которые не поддерживали режим косвенной регистровой адресации. В пастоятцее время самомодифицирующиеся программы считаются неудобными и трудными для понимания. Кроме того, их нельзя выполнять совместно несколькими процессорами.
Они не могут правильно выполняться даже на машинах с разделенной кэш-памятью первого уровня, если в кэш-памяти команд нет специальной схемы для обратной записи (поскольку разработчики предполагали, что программы сами себя изменять не должны). Индексная адресация Листинг 5.2. Программа на ассемблере, выполняющая операцию ИЛИ для 1024 элементов массива МОУ РЕМО ; собирает резул~та~ы выполнения ИПИ в В( , изначал~но а , В2 = инденс. т от текущего , произведения Я(т] И В[т] , РЗ = первое ненужное значение индекса Мат' В2.40 мау дз.ФАО96 [ООР. Маа Р4.А(Р2] ЯМО Д4,Вга2] ОД Д],Д4 ЯОО В2,т?4 СМР Д2.ДЗ В[Т (ООР Рд = А[т] Д4 = А(т] И В(т] т = т + 4 .
нужно ли продолжать? ; если В2 ч ВЗ, нужно продолжать Часто нужно уметь обращаться к словам памяти по известному смещению. Подобные примеры мы видели в машине 11'т(М, тле локальные переменные определяются по смещению от регистра ЕЯЯ. Обращение к памяти по регистру и константе смещения называется индексной адресацией. В машине 1З'т?М при доступе к локальной переменной используется указатель ячейки памяти (ЕЪ') в регистре плюс небольшое смещение в самой команде, как показано на рис. 4.14, а. Есть и другой способ: указатель ячейки памяти в команде и небольшое смещение в регистре.
Чтобы показать, как работает этот механизм, рассмотрим следующий пример. Пусть у нас есть два одномерных массива А и В по 1024 слова в каждом. Нам нужно вычислить А, И В; для всех пар, а затем соединить все эти 1024 логических произведения операцией ИЛИ, чтобы узнать, есть ли в этом наборе хотя бы одна пара, не равная нулто.
Один из вариантов — поместить адрес массива А в один регистр, а адрес массива  — в другой регистр, а затем последовательно перебирать элементы массивов аналогично тому, как мы делали в предыдущей программе (см. листинг 5.1). Такая программа, конечно же, будет работать, но ее можно усовершенствовать, как показано в листинге 5.2. 408 Глава 5. Уровень архитектуры набора команд Здесь нам требуется 4 регистра: + В1 — содержит результаты суммирования логических произведений; + В2 — индекс 4, который используется для перебора элементов массива; + ЙЗ вЂ” константа 4096 (это самое маленькое значение (, которое не исполь- зуется); + В4 — временный регистр для хранения каждого произведения. После инициализации регистров мы входим в цикл из шести команд.
Команда с меткой МООР вызывает элемент А, в регистр В4. При вычислении источника здесь используется индексная адресация. Регистр (В2) и константа (адрес элемента А) складываются, полученный результат служит для обращения к памяти. Сумма этих двух величин поступает в память, но не сохраняется ни в одном из доступных пользователю регистров. Следуклцая запись означает, что для определения приемника используется регистровая адресация, а для определения источника — индексная: МОЧ й4,АЯ2> Здесь й4 — это регистр, А — смещение, й2 — регистр. Если А имеет значение, скажем, 124 300, то соответствующая машинная команда будет выглядеть так, как показано на рис. 5.14.
Рис. 5.14. Возможное представление команды МОн п4, А(п2) в памяти Во время первого прохождения цикла регистр В2 принимает значение 0 (так регистр инициализируется), поэтому нужное нам слово Аа находится в ячейке с адресом 124 300. Это слово загружается в регистр В4. При следующем прохождении цикла В2 принимает значение 4, поэтому нужное нам слово А, находится в ячейке с адресом 124 304 и т.
д. Как мы отмечали, здесь смещение — это указатель ячейки памяти, а значение регистра — это небольшое целое число, которое во время вычисления меняется. Такая форма требует, чтобы поле смещения в команде было достаточно большим для хранения адреса, поэтому такой способ не очень эффективен, однако он часто оказывается самым лучшим. Относительная индексная адресация В некоторых машинах применяется режим адресации, при котором адрес вычисляется путем суммирования значений двух регистров и смещения (смещение факультативно).
Такой режим называется относительной индексной адресацией. Один из регистров — это база, другой — индекс. Относительная индексная адресация очень удобна при следующей ситуации. Вне цикла мы могли бы поместить адрес элемента А в регистр В5, а адрес элемента  — в регистр Вб. Тогда можно было бы заменить две первые команды цикла МООР: ОООР: МОЧ й4 Дй2+й5) АМО й4,(й2+йб) Адресация 409 Было бы идеально, если бы существовал режим адресации по сумме двух регистров без смещения. В то же время даже команда с 8-разрядным смещением была бы большим достижением, поскольку оба смещения можно сделать нулевыми.
Однако если смещение всегда составляет 32 бита, тогда мы ничего не выиграем, использовав такой режим адресации. На практике машины с относительной индексной адресацией обычно имеют форму с 8- или 16-разрядным смещением. Стековая адресация Мы уже отмечали, что очень желательно сделать машинные команды как можно короче. Предельный случай — команды без адресов. Как мы видели в главе 4, безадресные команды, например 1А00, возможны при наличии стека. В этом подразделе мы рассмотрим стековую адресацию более подробно.
Обратная польская запись В математике существует древняя традиция помещать оператор между операндами (х + у), а не после операндов (х у +). Форма с оператором между операндами называется инфиксной записью. Форма с оператором после операндов называется постфиксной, или обратной польской записью в честь польского логика Я.
Лукасевича (1958), который изучал свойства этой записи. Обратная польская запись имеет ряд преимуществ перед инфиксной записью при выражении алгебраических формул. Во-первых, любая формула может быть выражена без скобок. Во-вторых, она удобна для вычисления формул в машинах со стеками. В-третьих, инфиксные операторы имеют приоритеты, которые произвольны и нежелательны.
Например, мы знаем, что а Ь + с значит (а Ь) + с, а не а (Ь + с), поскольку произвольно было определено, что умножение имеет приоритет над сложением. Но имеет ли приоритет сдвиг влево над логической операцией И? Кто знает? Обратная польская запись позволяет устранить такие недоразумения. Существует несколько алгоритмов для превращения инфиксных формул в обратную польскую запись. Мы рассмотрим переработанный алгоритм, идея которого предложена Э. Дейкстра (Б. Ю. Р1)кзгга).