Э. Таненбаум - Архитектура компьютера (1127755), страница 71
Текст из файла (страница 71)
Из всех механизмов, которые )НМ применяет для этого, в 1)НМ мы включили два. В одном случае мы пропустили краткую форму в пользу более традиционной. В другом случае мы показываем, как префиксная команда И10Е может использоваться для изменения следующей команды. Наконец, существуют команда вызова другой процедуры (1МЧОКЕЧ1кТОАЕ) и команда выхода из текущей процедуры и возвращения к процедуре, из которой она была вызвана (1кЕТОкв). Из-за сложности механизма мы немного упростили определение. Ограничение состоит в том, что, в отличие от языка )ача, в нашем примере процедура может вызывать только такую процедуру, которая находится внутри нее. Хотя это ограничение противоречит сути языка )ача, оно позволяет представить более простой механизм без необходимости размещать процедуру динамически.
(Если вы не знакомы с объектно-ориентированным программированием, можете игнорировать это предложение. Мы просто превратили язык )ача из объектно-ориентированного в обычный, такой как С или Разса1.) На всех компьютерах, кроме ) НМ, адрес процедуры, которую нужно вызвать, непосредственно определяется командой САЕЕ, поэтому наш подход скорее правило, чем исключение. Механизм вызова процедуры состоит в следующем. Сначала вызывающая программа помещает в стек указатель на вызываемый объект. На рис. 4.10, а этот указатель обозначен символами ОВ)КЕГ.
Затем вызывающая программа помещает в стек параметры процедуры (в данном примере — это Параметр 1, Параметр 2 и Параметр 3). После этого выполняется команда 1йЧОКЕЧ1кТОАЕ Команда 1йЧОКЕЧ1кТОАЕ включает в себя относительный адрес (ЙОт), указывающий на позицию в наборе констант. В этой позиции находится начальный адрес вызываемой процедуры, которая хранится в области процедур.
Первые 4 байта в области процедур содержат специальные данные. Первые 2 байта представляют собой целое 16-разрядное число, указывающее на количество параметров данной процедуры (сами параметры были ранее помещены в стек). В данном случае указатель ОВ)йЕГ считается параметром — параметром О.
Это 16-разрядное целое число вместе со значением БР дает адрес ОВ)КЕГ. Отметим, что регистр ЕЪ' указывает на ОВ)КЕГ, а не на первый реальный параметр. Выбор того, на что указывает ЕН, в какой-то степени произволен. Следующие 2 байта в области процедур представляют еще одно 16-разрядное целое число, задающее размер области локальных переменных для вызываемой процедуры. Дело в том, что для данной процедуры предоставляется новый стек, который размещается прямо над фреймом локальных переменных, для этого и нужно это число. Наконец, пятый байт в области процедур содержит код первой операции, которую нужно выполнить. 284 Глава 4. Уровень микроархитектуры Стек после выполнения команды 1МНОКЕН1ЙТ(!АГ ЗР Стек до выполнения команды 1МНОКЕН(НТ(!А1 Основание стека ЗР после выполнения команды !МНОКЕН(ИТ(!А1.
Вьлопкнутые из стека параметры ГН Фрейм локальных переменных вызывающей процедуры Основание стека до выполнения команды 1МНОКЕН!ИТ(!А(. ГН Рис. 4.10. Память до выполнения команды (МНОКЕН!ВТ((АЬ (а); память после выполнения этой команды (б) Посмотрим, что происходит перед вызовом процедуры (см. также рис. 4.10). Два байта без знака, которые следуют за кодом операции, используются для индексирования таблицы констант (первый байт — старший).
Команда вычисляет базовый адрес нового фрейма локальных переменных. Для этого из указателя стека вычитается число параметров, а 1Л' устанавливается на ОВ) ВЕЕ. В ОВ! йЕР хранится адрес ячейки, в которой находится старое значение РС. Этот адрес вычисляется следующим образом. К размеру фрейма локальных переменных (параметры е локальные переменные) прибавляется адрес, содержащийся в регистре ЕЪ'. Сразу над адресом, предназначенным для сохранения старого значения РС, находится адрес, в котором должно быть сохранено старое значение ЕЧ. Над этим адресом начинается стек для новой вызванной процедуры.
БР указывает на старое значение ЕЧ, адрес которого находится сразу под первой пустой ячейкой стека. Помните, что ЯР всегда указывает на верхнее слово в стеке. Если стек пуст, то ВР указывает на адрес, который находится непосредственно под стеком, поскольку стек заполняется снизу вверх. Пример архитектуры набора команд — ОНМ 285 И наконец, для выполнения команды 1МЧОКЕЧ)МТОАЕ нужно сделать так, чтобы регистр РС указывал на пятый байт в кодовом пространстве процедуры.
Команда 1ЯЕТОММ противоположна команде 1МЧОКЕЧ1МТОАЕ (рис. 4.11). Она освобождает пространство, используемое процедурой. Она также возвращает стек в предыдущее состояние, за исключением того, что, во-первых, ОВ) КЕР и все параметры удаляются из стека; во-вторых, возвращенное значение помещается в стек, туда, где раньше находился параметр ОВ) КЕК Чтобы восстановить прежнее состояние, команда 1МЕТОММ должна вернуть прежние значения указателей РС и 1Л'. Для этого она обращается к связующему указателю (это слово, определяемое текущим значением (Л').
В этом месте, где изначально находился параметр ОВ)КЕР, команда 1МЧОКЕЧ1МТОАЕ сохранила адрес, содержащий старое значение РС. Это слово, а также слово над ним извлекаются, чтобы восстановить старые значения РС и 1Л' соответственно. Возвращенное значение, которое хранится на самой вершине стека завершающейся процедуры, копируется туда, где изначально находился параметр ОВ)КЕГ, после чего ЯР начинает указывать на этот адрес. И тогда управление переходит к команде, которая следует сразу за 1МЧОКЕЧ1МТЬЧ.. Стек до выполнения команды ЯЕТОНМ Стек после еыполнения команды )ЙЕТОЙМ Основание стека до аыпопнения команды (НЕТОНМ (.Н Фрейм локальных переменных вызывающей процедуры Основание стека после выполнения команды ЯЕТОНМ (.Н Рис. 4.11. Память до выполнения команды! НЕТОЯМ (а); память после выполнения этой команды (б) 286 Глава 4.
Уровень микроархитектуры До сих пор у нашей машины не было никаких команд ввода-вывода. Мы и не собираемся их вводить. В нашем примере, как и в виртуальной машине )ача, они не нужны, и в описании 3'х/М никогда не упоминаются процессы ввода-вывода. Считается, что машина без механизмов ввода-вывода более надежна. (Чтение и запись осуществляются в ! 1/М путем вызова специальных процедур.) Компиляция ЦЧМ А теперь посмотрим, какое отношение язык Зача имеет к 1!'х/М. В листинге 4.1 представлен небольшой фрагмент программы на языке Зача. Компилятор Зача должен был бы переделать эту программу в программу на языке ассемблера 1)'х/М, приведенную в листинге 4.2.
Цифры с 1 по 15 в левой части листинга, а также комментарии после символов двойной косой черты (//) не являются частью самой программы. Они даны для наглядности и просто облегчают понимание. Затем ассемблер 3ача транслировал бы ее в программу в двоичном коде. Эта программа представлена в листинге 4.3. (В действительности результатом работы компилятора Зача сразу является двоичный код.) В данном примере 1 — локальная переменная 1,,! — локальная переменная 2, а !г — локальная переменная 3.
Листинг 4.1. Фрагмент программы на языке Зача !П!==3! Х=О; е1хе 3=3-1. Листинг 4.2. Программа для ОУМ на языке ассемблера дача 1 1ЕОАО 3 // !=З~-Е 2 110АО Х 3 !АОО 4 15ТОВЕ ! 5 110АО ! О 1 П 1==3) б В1Р05Н 3 7 !г 1ЕНРЕО Е! В !10АО 3 О 3=3-1 9 В1Р05Н 1 10 150В 11 15ТОНЕ 3 12 ВОТО Е2 13 Щ: В!РОЗН О О 1=О 14 15ТОНЕ Х 15 12. Листинг 4.3. Программа для ЦУМ в шестнадцатеричном коде Ох15 Ох02 Ох15 ОхОЗ ОхбО Охзб Ох01 Ох15 Ох01 Ох10 ОхОЗ Ох9Г Ох00 Ох00 Ох15 Ох02 Ох!0 Ох01 Пример реализации микроархитектуры 287 Ох64 Охзб Ох02 Оххт Ох00 Ох07 Ох10 Ох00 Охзб Ох03 Скомпилированная программа проста. Сначала 3 и ~ помещаются в стек, складываются, а результат сохраняется в 1. Затем 1 и константа 3 помещаются в стек и сравниваются.
Если они равны, то совершается условный переход к 1.1, где 2 получает значение О. Если они не равны, то выполняется часть программы после команды 1Г 1СМРЕ0. После этого осуществляется переход к 1.2, где объединяются части е1 хе и слеп. Стек операндов для программы, приведенной в листинге 4.2, изображен на рис. 4.12.
До начала выполнения программы стек пуст, что показано горизонтальной чертой над цифрой О. После выполнения первой комютды 11.0А0 3 помещается в стек (прямоугольник над цифрой 1 на рисунке). Цифра 1 означает, что выполнена первая команда. После выполнения второй команды 11.0А0 в стеке оказываются уже два слова, как показано в прямоугольнике над цифрой 2. После выполнения команды 1А00 в стеке остается только одно слово, которое представляет собой сумму 3' + 1г.