/
Теги: приборы, устройства, аппараты с механизмами передачи или с подвижными механизмами радиоэлектроника
ISBN: 5-03-000011-9
Текст
ЛБек W «
ВВЕДЕНИЕ
В СИСТЕМНОЕ
ПРОГРАММИРОВАНИЕ
Перевод с английского
Н. А. Богомолова, В. М. Вязовского и
С. Е. Морковина
под редакцией
Л. Н. Королева
МОСКВА «МИР» 1988
ББК 32 973
Б 42
УДК 681.142
Бек Л.
Б 42 Введение в системное программирование-Пей с
М.: Мир, 1988. - 448 с., ил. 1 а11г-' -
ISBN 5-03-000011-9
Монография учебного характера, написанная американским слеп
В ней изложены все основные компоненты системного программно, ?ИгЛист'
ния. Особое внимание уделено их взаимосвязи с архитектурой вычигпи''‘*
комплексов. Конкретные реализации компонентов обсуждаются и/, шшк'И;и 111 4
современных вычислительных систем: IBM/370, VAX, CYBER. ' ере к
Для системных программистов, аспирантов, студентов вузов.
1702070000—268 лл QQ t
Б —M7W=88— 44~88' -• ’
ББК 32. 973
Редакция литературы по математическим наукам
Учебное издание
Леланд Л. Бек
ВВЕДЕНИЕ В СИСТЕМНОЕ ПРОГРАММИРОВАНИЕ
Б. В. Шабат
Заведующий редакцией д-р физ.-мат. наук профессор
Зам. зав. редакцией А. С. Попов
Научи, редактор М. В. Хатунцева
Мл. редактор Т. ГО. Дехтярева
Художник Н. М. Иванов
Художественный редактор В. И. Шаповалов
Технический редактор Л. П. Емельянова
Корректор М. А. Смирнов
ИБ № 6315
Сдано в набор 25.08.87. Подписано к печати 18.05.88. Формат 60X90/16. - ,
Бумага книжно-журнальная. Печать высокая. Гарнитура литературная. Объем 11 >
Усл. печ. л. 28. Усл. кр.-отт. 28. Уч.-изд. л. 32,75. Изд. Ns 1/5213.’ Тираж 50000 экз.
Зак. 792. Цена 2р.Ь0.к
ИЗДАТЕЛЬСТВО «МИР» 129820, ГСП, Москва, И-110, 1-й Рижский пер., 2
’5 . Зб'З’
Ленинградская типография № 2 головное предприятие ордена Трудового Кг*‘vf 1 \-
мени Ленинградского объединения «Техническая книга» им. Евгении Сон’1'1 ।
нолиграфпрома при Государственном комитете СССР пи делам издательс^’. 11 •'
и книжной торговли. 198025, г. Ленинград, Л-52, Измайловский проспект, 2J.
ISBN Б-ОЗ-ОООО11-9 (русск.
ISBN 0-201 10950-6 (англ.)
© 1985 by Addison-Wcslev
Company. Inc ..
© перевод на русский >*
1988
От редактора перевода
Предлагаемая вниманию читателей книга
ваться как учебное пособие по курсу «Системное ппг?пССМаТрИ<
ванне». Ее несомненное достоинство_хооопю ППтР 1РаммиРО’
тоднка представления материала и разумный комт?пнмННаЯ Ме<
ду детальностью изложения конкретных элементовР системного
программного обеспечения и общими сведениями обос^вГьх
концепциях, принятых при создании этих элементов Эта мето*
дика автора заключается в следующем: сначала рассматривав
ются машинно-независимые характеристики того или иного ком-
понента оазового программного обеспечения, затем следует из-
ложение того, как реализованы эти компоненты на конкретных
ЭВМ. В качестве таких ЭВМ автор выбрал очень непохожие
друг на друга: System/370, VAX и CYBER. Примеры систем-
ных программ приводятся для двух выдуманных автором упро-
щенных учебных машин, которые по своей структуре очень
близки к современным микропроцессорам. Это дает возмож-
ность читателю достаточно детально понять, как программиру-
ются отдельные компоненты, одновременно не теряя из виду
общей картины взаимосвязи компонентов системного программ-
ного обеспечения; в то же время он получает информацию о
том, как все это реализовано на настоящих машинах. В отли-
чие от ряда других переводных изданий данная книга не
ориентирована на какой-то определенный класс машин и кон-
кретный состав программного обеспечения, а дает более широ-
кое представление о характеристиках и свойствах системных
программ.
Следует отметить умение автора просто и понятно расска-
зать о принципах реализации таких сложных элементов компи-
ляторов, как рекурсивные процедуры, окна видимости данных,
машинно-независимая и машинно-зависимая 0ПТИМ”3Д^.,
генерируемого объектного кода, о построении повторно в. с.
МЫИзРобщсгРо стиля изложения несколько^ вь,пада^ Г/0Лжны
основном содержащая перечень требовании, ко Р ение ба.
удовлетворять такие важные компоненты, к 4 УеоРктивной от-
зами данных, текстовые редакторы, спет > Р
ЛаДАвтор иногда отступает от общепринятой
вводит свои термины. Например, и
адрес». Этот термин вполне уместен: им обозначается некото-
рым образом вычисленный код, который используется в каче-
стве либо исполнительного адреса, либо косвенного адреса,
либо непосредственного операнда. Автор в одном и том же
смысле употребляет термины «архитектура» и «структура»
ЭВМ и не делает различия между терминами «компиляция» и
«трансляция», однако это не приводит к недоразумениям. При
переводе книги сохранена терминология автора и в тех слу-
чаях, когда это необходимо по тексту, даны соответствующие
примечания.
Данная книга будет полезна многим читателям, и прежде
всего преподавателям вузов, ведущих занятия по системному
программированию, и разработчикам системных программ. Она
будет полезна учителям средних школ, преподающих основы
информатики и вычислительной техники и ведущим факульта-
тивные занятия по данному предмету. Несомненно, она послу-
жит хорошим пособием для студентов, специализирующихся в
области системного программного обеспечения ЭВМ.
Л. Н. Королев
Предисловие
Эга книга представляет собой введение в проектирование и
реализацию компонентов системного программного обеспечения
Ес центральная тема — взаимосвязь между архитектурой ЭВМ
и системными программами. Примерами системных компонен-
тов. которые испытывают значительное влияние со стороны ма-
шинной архитектуры, являются ассемблеры и операционные си-
стемы. Чтобы особо подчеркнуть и продемонстрировать такое
влияние, мы рассмотрим реально существующие компоненты
системных программ для целого ряда машин. Однако программ-
ное обеспечение различных вычислительных систем имеет и
сходные черты (например, базовая структура и схема ассембле-
ра по существу одни и те же для большинства ЭВМ). Эти ос-
новные машинно-независимые аспекты системных программ
четко определяются и отделяются от деталей, обусловленных
спецификой конкретной ЭВМ.
Основное назначение настоящей книги — служить учебным
пособием для студентов, а также аспирантов по курсу «Систем-
ное программное обеспечение» или «Системное программирова-
ние». Ею также можно воспользоваться в качестве справочника
или пособия для самостоятельного изучения этих дисциплин.
Предполагается, что читатель знаком по крайней мере с одним
нз языков ассемблера и общими методами представления
команд и данных в памяти ЭВ;М (например, восьмеричной и
шестнадцатеричной нотацией, представлением отрицательных
чисел в обратном и дополнительном кодах). Эти темы хорошо
рассмотрены в работах Пфл игера [1982] и Гира [1981]. Кроме
того, предполагается знакомство читателя с методами исполь-
зования базовых структур данных, в особенности связанных
списков и хеш-таблиц. Материал по этим темам можно найти
в любом хорошем учебнике по структурам данных, например у
Трембли и Соренсона [1984], Стендиша [1980] или Кнута
||1973а,б|.
В гл. 1 содержится краткое введение и описывается упро-
шенная учебная машина (УУМ), используемая для представле-
ния основных концепций программного обеспечения. В ней так-
же описываются реальные вычислительные системы (о\
stcm/370, VAX, CYBER), которые в дальнейшем используются
в качестве примеров. Эти машины резко различаются по своей
архитектуре, и поэтому они были выбраны для иллюстрации
разнообразия программных и аппаратных систем.
Глава 2 посвящена вопросам разработки ассемблеров.
В разд. 2.1 в качестве учебного инструмента для пре ц ыикн-
нич базовых концепций ассемблирования программ использует-
ся УУМ. Ввиду того что основные функции и характеристики
ассемблера слабо зависят от конкретной машины, этот мате-
риал может служить студенту отправной точкой при проекти-
ровании ассемблера для новой или ранее не знакомой ему
ЭВМ. В разд. 2.2 обсуждаются машинно-зависимые аспекты
расширения базовых функций ассемблера, описанных в
разд. 2.1. Такое обсуждение помогает подчеркнуть взаимосвязь
между архитектурой ЭВМ и теми решениями, которые прини-
мают при проектировании и реализации ассемблеров.
В разд. 2.3 вводится ряд машинно-независимых средств ассемб-
леров, а в разд. 2.4 обсуждаются некоторые важные альтерна-
тивные варианты общей схемы ассемблирования. Наличие воз-
можностей, описанных в разд. 2.3, так же как и выбор схемы
ассемблирования, не диктуется машинными особенностями, а
определяется разработчиком программного обеспечения. Здесь
нет какого-либо единственно «правильного» способа реализации.
Поэтому разработчик программного обеспечения должен отда-
вать себе полный отчет в существовании других решений для
того, чтобы сделать разумный выбор между ними. Наконец, в
разд. 2.5 обсуждаются примеры существующих ассемблеров для
реальных ЭВМ. Эти примеры иллюстрируют как машинно-за-
висимые, так и машинно-независимые варианты решения тех
или иных вопросов, что существенно дополняет материал, рас-
смотренный в предыдущих разделах.
Аналогичный общий подход используется при обсуждении
загрузчиков (гл. 3), макропроцессоров (гл. 4), компиляторов
(гл. 5) и операционных систем (гл. 6). Вначале описываются
базовые характеристики рассматриваемого системного компо-
нента. Затем следует обсуждение машинно-зависимых и машин-
но-независимых возможностей, расширяющих базовые функции.
Далее рассматриваются другие возможные подходы к проекти-
рованию и даются примеры реальных системных программ.
Глубина изложения материала в различных главах значи-
тельно варьируется. Главы 2—4 содержат достаточно полное
обсуждение ассемблеров, загрузчиков и макропроцессоров. Опи-
сываемые здесь детали реализации (алгоритмы и структуры
данных) должны в принципе позволить студенту самостоятельно
написать работающий вариант системной программы на основе
приведенных схем. (Я настоятельно рекомендую, чтобы курс,
основанный на данной книге, предусматривал такой проект.)
С другой стороны, темы, затрагиваемые в гл. 5 и 6, значи-
тельно шире. Каждая из них сама по себе являлась предметом
многих отдельных монографий. Очевидно, что невозможно
сколько-нибудь полно обсудить их в рамках одной главы. Вме-
сто этого ставилась задача дать читателю краткий (по огню о
ш поверхностный) обзор компиляторов и операционных систем.
in ... .... -...........................................—
Наиболее важные и фундаментальные концепции данных ком-
понентов программного обеспечения иллюстрируются на приме-
рах. Более сложные вопросы лишь отмечаются в тексте, а для
читателя, желающего рассмотреть их более глубоко, даются
ссылки на соответствующую литературу. Из-за недостатка мес-
та большинство деталей реализации было опущено. Аналогич-
ный подход использован в гл. 7, посвященной системам управ-
ления базами данных, текстовым редакторам и интерактивным
системам отладки.
Упражнения, приведенные в конце гл. 2—6, являются важ-
ной составной частью книги. Они предназначены для стимули-
рования индивидуального мышления и дискуссий в аудитории.
Некоторые из этих упражнений представляют собой открытые
проблемы, не имеющие единственного «правильного» ответа.
Многие упражнения требуют от читателя умения применить
понятия, изложенные в основном тексте, к новым ситуациям.
Успешное решение предлагаемых упражнений является гаран-
тией того, что читатель глубоко усвоил рассмотренные принци-
пы и в состоянии использовать их в практической работе.
Я намеренно не включил в книгу ответы на упражнения, так
как полагаю, что список ответов был бы скорее фактором, сдер-
живающим творческое мышление, нежели стимулирующим его.
Объем книги превышает обычный односеместровый курс, что
позволяет преподавателю выбрать нужную степень глубины из-
ложения различных тем в зависимости от потребностей кон-
кретного учебного плана. Например, если предполагается, что
впоследствии студенты будут слушать специальный курс по
операционным системам, то преподаватель может опустить
гл. 6, при этом материала оставшихся глав будет достаточно
для типового односемсстрового курса. Другие преподаватели
могут предпочесть рассмотрение всех основных глав, исключив
некоторые разделы, в которых обсуждаются более сложные
вопросы.
Одним из моментов, заслуживающих комментария, является
применение для целей обучения гипотетической ЭВМ (УУМ).
Я использовал гипотетическую машину в первую очередь пото-
му, что это позволяет избежать не связанных с существом дела
сложностей и «причуд», встречающихся в реальных машинах.
Кроме того, использование такой машины позволяет четко от-
делить фундаментальные концепции тех или иных компонентов
программного обеспечения от деталей реализации, связанных
со спецификой ЭВМ. Если для целей обучения используется
реальная машина, то у студента не всегда есть уверенность в
том, что он правильно понимает, какие характеристики про-
граммною обеспечения являются действительно фундаменталь-
ными, а какие просто следствием использования конкретной
эвм,
О
Наиболее важные в фундаментальные концепции данных ю м
понентов программного обеспечения иллюстрируются на приме
рах. Более сложные вопросы лишь отмечаются в тексте а для
читателя, желающего рассмотреть их более глубоко ’даются
ссылки на соответствующую литературу. Из-за недостатка мес-
та большинство деталей реализации было опущено. Аналогич-
ный подход использован в гл. 7, посвященной системам управ-
ления базами данных, текстовым редакторам и интерактивным
системам отладки.
Упражнения, приведенные в конце гл. 2—6, являются важ-
ной составной частью книги. Они предназначены для стимули-
рования индивидуального мышления и дискуссий в аудитории
Некоторые из этих упражнений представляют собой открытые
проблемы, не имеющие единственного «правильного» ответа.
Многие упражнения требуют от читателя умения применить
понятия, изложенные в основном тексте, к новым ситуациям.
Успешное решение предлагаемых упражнений является гаран-
тией того, что читатель глубоко усвоил рассмотренные принци-
пы и в состоянии использовать их в практической работе.
Я намеренно не включил в книгу ответы на упражнения, так
как полагаю, что список ответов был бы скорее фактором, сдер-
живающим творческое мышление, нежели стимулирующим его.
Объем книги превышает обычный односеместровый курс, что
позволяет преподавателю выбрать нужную степень глубины из-
ложения различных тем в зависимости от потребностей кон-
кретного учебного плана. Например, если предполагается, что
впоследствии студенты будут слушать специальный курс по
операционным системам, то преподаватель может опустить
гл. 6, при этом материала оставшихся глав будет достаточно
для типового односеместрового курса. Другие преподаватели
могут предпочесть рассмотрение всех основных глав, исключив
некоторые разделы, в которых обсуждаются более сложные
вопросы.
Одним из моментов, заслуживающих комментария, является
применение для целей обучения гипотетической ЭВМ (УУМ).
Я использовал гипотетическую машину в первую очередь пото-
му, что это позволяет избежать не связанных с существом дела
сложностей и «причуд», встречающихся в реальных машинах.
Кроме того, использование такой машины позволяет четко от-
делить фундаментальные концепции тех или иных компонентов
программного обеспечения от деталей реализации, связанных
со спецификой ЭВМ. Если для целей обучения используется
реальная машина, то у студента не всегда есть уверенность в
том, что он правильно понимает, какие характеристики про-
граммного обеспечения являются действительно фундамеиiзон-
ными, а какие — просто следствием использования конкретен
ЭВМ.
Второе преимущество использования УУМ заключается „
том, что практически все студенты будут иметь одинаковую
начальную подготовку, т. е. не будет студента, который 0L
жется в худшем положении из-за того, что он незнаком с кон-
кретной ЭВМ и ее программным обеспечением, положенными
в основу книги. Я считал, что это будет особенно важно в мп
ем курсе, который предназначен для студентов, имевших опыт
работы с различными машинами.
в мо-
Само собой разумеется, что при изучении подобного курса
студенты должны иметь возможность писать программы и про-
пускать их на машине, которую они изучают. Интерпретатор
УУМ может эксплуатироваться практически на любой ЭВМ
поддерживающей Паскаль. Это дает студентам возможность
разрабатывать и пропускать системные программы так, как
если бы они на самом деле имели доступ к УУМ. Наличие пе-
реносимого интерпретатора означает, что нет необходимости в
использовании какой-либо конкретной вычислительной систе-
мы, так как программы для УУМ могут выполняться на любой
ЭВМ, удобной для преподавателя и студентов.
Наконец, следует заметить, что некоторые из рецензентов
вначале скептически относились к УУМ, но изменили свое мне-
ние, увидев, как она может быть использована в качестве учеб-
ного инструмента.
Многие отдали время и энергию для улучшения этой книги.
Я хочу выразить особую признательность Саре Баас за то, что
она с самого начала моей работы над книгой делилась со мной
своим опытом автора. Сара Баас, Стив Брюел, Тим Будд, Род-
жер Кинг, Томас Ньюджент, Чарльз Пфлигер, Поль Росс, Вер-
нор Винг и Бернард Уейнберг отрецензировали значительные
части рукописи. Их замечания и предложения были крайне по-
лезны для меня при выискивании ошибок и решении других
проблем, связанных с рукописью. За все ошибки, которые гем
не менее остались в тексте, отвечаю я лично и буду весьма
признателен всем, кто укажет мне на них. г
Я хотел бы поблагодарить Мэтта Белшина, Джеффа 4
мона, Пэта Коффеи, Глена Джерпсета, Сэнду Швиммер и х
Свенсона за их помощь в поиске справочного материал ~
конкретным системам. Я также в долгу перед стУдснтам’’тве
торые использовали предварительный вариант, книги в ка t
учебника и сделали много ценных предложении. ппузьям,
Наконец, я глубоко признателен моей жене, семье,
коллегам и студентам за ту атмосферу понимания и по .
которую они создали мне в период, когда мое время i
гия были отданы работе над книгой. Без их терпения i
довс-
рия эта работа продвигалась бы гораздо труднее.
Август 1984 г.
Л. Л. Б.
Глава 1. Основные понятия
В данной главе содержится различная информация, которая
послужит нам основой при изучении последующих глав
В разд. 1.1 приводится обзор структуры книги и дается крат-
кое введение в системное программное обеспечение. С разд 1 2
начинается обсуждение взаимосвязи между системным про-
граммным обеспечением и структурой ЭВМ, которое продол-
жится в дальнейшем на протяжении всей книги. В разд. 1.3—
1.7 даются общие сведения об архитектуре некоторых ЭВМ,
используемых далее в качестве примеров. Более детальное
обсуждение большинства вопросов, касающихся архитектуры
машин, можно найти в работах Танненбаум 119841, Пфлигео
|1982] и Гир [1981].
Основная часть данной главы содержит лишь общие сведе-
ния; многие детали опущены. Уровень детализации выбран та-
ким, чтобы он обеспечивал лучшее понимание последующих
глав. Не следует стремиться запоминать материал этой главы
или углубляться в малозначительные вопросы. Вместо этого
рекомендуется главу прочитать, а затем, при изучении после-
дующих глав, использовать ее по мере необходимости в каче-
стве справочника. Для читателей, желающих получить более
подробную информацию по тем или иным вопросам, проводят-
ся необходимые ссылки на литературу.
1.1. Введение
Эта книга является введением в проектирование различных
компонентов системного программного обеспечения. Мы также
рассмотрим реализацию такого программного обеспечения для
некоторых реально существующих машин. Одна из централь-
ных проблем книги — взаимосвязь системного программного
обеспечения и архитектуры ЭВМ. Очевидно, что структура це-
левой машины оказывает влияние на выбор тех или иных ре-
шений, применяемых при создании системных программ. Неко-
торые аспекты такого влияния обсуждаются в разд. 1.2, другие
будут рассмотрены в остальных главах книги.
Основные темы, которые рассматриваются в данной книге,
касаются ассемблеров, загрузчиков, макропроцессоров, компи-
ляторов и операционых систем. Каждая из гл. 2 6 посвящена
одной из них. Предполагается, что с точки зрения пользователя
читатель знаком со всеми рассматриваемыми здесь системными
компонента ми. В первую очередь в данной книге затрагивают-
ся вопросы проектирования и реализации системного обеспече-
ния. В гл. 7 содержится обзор некоторых других важных си-
стемных компонентов: систем управления базами данных, тек-
стовых редакторов и систем интерактивной отладки.
Глубина изложения материала неодинакова. Главы, посвя-
щенные ассемблерам, загрузчикам и макропроцессорам’, содер-
жат достаточно детальную информацию, позволяющую подгото-
вить читателя к тому, чтобы он мог самостоятельно написать
данные компоненты программного обеспечения для реальных
машин. С другой стороны, компиляторы и операционные систе-
мы являются слишком обширными темами, каждая из которых
сама по себе не раз была объектом многих отдельных моно-
графии и курсов. Очевидно, что невозможно полностью рассмо-
треть какую-либо из этих тем в одной главе сколько-нибудь
разумного размера. Поэтому вместо этого предлагается введе-
ние в наиболее важные понятия и вопросы, относящиеся к ком-
пиляторам и операционным системам; особое внимание уделя-
ется взаимосвязи программного обеспечения и структуры ЭВМ.
Другие подтемы обсуждаются настолько, насколько позволяет
место, и снабжаются ссылками на литературу, предназначенны-
ми для читателей, желающих изучить их более глубоко. Наша
цель — дать хороший общий обзор рассматриваемых тем, кото-
рый мог бы послужить в дальнейшем базой при изучении сту-
дентами специальных курсов по программированию. Аналогич-
ный подход используется и при изложении материала гл. 7.
1.2. Системное программное обеспечение и
структура ЭВМ
Машинная зависимость является одной из характеристик,
которая обычно отличает системное программное обеспечение
от прикладного. Прикладная программа интересует пас ’у13’'
иым образом с точки зрения решения некоторой задачи. I
этом ЭВМ используется как инструмент и основное впим
сосредоточено на предметной стороне дела, а не на выч •'
тельной системе. С другой стороны, системные программу Р '
назначены скорее для обеспечения управления ФУи1^и1 , пет.
нием собственно ЭВМ, чем для решения какой-либо ч
ной задачи. Вследствие этого они обычно тесно св ‘ ’ м(-р
структурой машины, для которой созданы. IIапрпмер, *
леры при переводе мнемонических инструкции в ма|1’ ’пч.а.
непосредственно учитывают форматы команд, спосо ’ • • .
ции и другие аппаратные характеристики целен
Jj. Систему программ,l0c обеспечение
Компиляторы должны генерировать код на мя.„
учитывая такие характеристики аппаратуры как Язь,ко’
соб использования регистров или имеющиеся £ nJ ° и спо'
ды. Операционные системы непосредственно отвечают”'' Т*"'
ление практически всеми ресурсами вычислительной 3"управ'
В дальнейшем мы увидим много других поимепп? СИСТСМЬ,П’
зависимости. других примеров машинной
С другой стороны, системное программное обеспечение имеет
ряд аспектов, непосредственно не связанных с типом вычисли,
тельной системы, которую они поддерживают. Так общая eJ
ма и алгоритмы ассемблера в основном не различаются для
большинства ЭВМ. Некоторые из способов оптимизации объект,
ного кода, используемые в компиляторах, не зависят от цечс.
вой машины (хотя существует также и машинно-зависимая
оптимизация). Точно так же обычно не зависит от используе-
мой ЭВМ и процесс установления связей между отдельно ас-
семблированными подпрограммами в последующих главах
мы рассмотрим много других примеров аналогичных машинно-
независимых характеристик.
Ввиду того что большинство системных программ машинно-
зависимые, мы должны в процессе обучения рассматривать ре-
альные машины и реальные компоненты программного обеспе-
чения. Однако большинство реальных ЭВМ обладает определен-
ными нестандартными или даже уникальными особенностями.
Поэтому порой бывает трудно отличить действительно основ-
ные свойства программного обеспечения от свойств, зависящих
исключительно от специфических особенностей конкретной ма-
шины. Для того чтобы обойти эти трудности, мы для изуче-
ния основных функций каждого из компонентов программного
обеспечения будем использовать Упрощенную Учебную Машину
(УУМ). УУМ представляет собой гипотетическую ЭВМ, при
проектировании которой ставилась цель включить в нес апла
ратные возможности, наиболее часто встречающиеся в рса.
ных ЭВМ, исключив в то же время не относящиеся к сушест у
дела или редко встречающиеся сложности. Таким °’р п ’
новные концепции каждого компонента системного р Р ‘
го обеспечения могут быть четко отделены 0Т„А^ 1 ст чи,
ции, связанных с конкретной машиной. Такой ш; - _ 'оекти.
тателю отправную точку, с которой он может < ’ювой или
рование системного программного обеспечен») ,
ранее незнакомой ему ЭВМ. начинается с опи-
Каждая основная глава книги (гл. 2 системного
сания базовых функций обсуждаемого кох
„„ Гппсобы установления связен
Утверждение автора не совсем том • / ровацными программами
и передачи параметров между раздельно 6‘ H0CPejj ЭВМ. — Прим. ре<-•
зависят очень заметно от структурных особенностей
обеспечения. Затем рассматриваются машинно-независимые
функции, являющиеся расширением базовых. В заключительной
части главы содержатся примеры реализации системных про-
грамм для реальных машин. Основные главы содержат следую-
щие разделы:
1. Основные функции, свойственные данному типу программ-
ного обеспечения и не зависящие от реализации.
2. Возможности, наличие и особенности которых тесно свя-
заны с машинной архитектурой.
3. Другие возможности, которые имеют относительную ма-
шинную независимость и характерны для большинства реали-
заций программного обеспечения данного типа.
4. Основные варианты построения конкретных компонентов
программного обеспечения (например, однопросмотровый раз-
бор в сравнении с многопросмотровым).
5. Примеры реализации для реальных ЭВМ, в которых ос-
новное внимание уделяется нестандартным свойствам программ-
ного обеспечения, связанным с машинными характеристиками.
В данной главе содержатся краткие описания реальных
ЭВМ, В дальнейшем эти машины будут использоваться для
иллюстрации обсуждаемого материала. Сейчас мы предлагаем
вам прочитать эти описания, а затем обращаться к ним, когда
это необходимо, при изучении приводимых в каждой главе при-
меров.
1.3. Упрощенная учебная машина (УУМ)
В этом разделе мы опишем архитектуру нашей УУМ. Эта
машина была спроектирована для того, чтобы проиллюстриро-
вать наиболее часто встречающиеся аппаратные концепции и
возможности, избегая в то же время большинства специфиче-
ских особенностей, присущих реальным машинам.
Во многих отношениях УУМ похожа на типичную микро-
ЭВМ. Подобно многим другим ЭВМ, которые выпускаются про-
мышленостыо, УУМ имеется в двух вариантах: в виде стан-
дартной модели и модели УУМ/ДС (где индекс ДС означает
с «дополнительными средствами» или, возможно, за «дополни-
тельную стоимость»). Оба варианта спроектированы таким оо-
разом, чтобы обеспечивалась совместимость «снизу вверх». Эк>
означает, что объектная программа для стандартной модели
УУМ будет правильно выполняться и на УУМ/ДС. (Такая
совместимость часто встречается в реально существующих се-
мействах ЭВМ.) Характеристики стандартной модели У<
описываются в разд. 1.3.1, а дополнительные возможности,
включенные в УУМ/ДС,—в разд. 1.3.2.
1£22^сная Учебная машнна (УУМ)
1.3.1. Структура УУМ
Память
Оперативная память состоит из 8-разпялнму г •
последовательных байта составляют слово (24 разпял?)%1Рм
имеет байтовую адресацию. Слова адресуются по Лп Ъ
с наименьшим номером. Общий объем оперативной п У баита
ставляет 32 768 (215) байт. ративнои памяти со-
Регистры
Имеется пять регистров, у каждого из которых есть собст-
венное назначение. В таблице, приведенной ниже, указаны
мнемонические имена регистров, их номера и назначение (Си-
стема нумерации регистров выбрана таким образом чтобы
была обеспечена совместимость с моделью УУМ/ДС.)
Имя Номер
Назначение
А 0 Сумматор. Используется при выполнении ариф-
метических операций
X 1 Индексный регистр. Используется для адресации
L 2 Регистр связи. Команда перехода на подпро-
грамму (JSUB) запоминает в этом регистре ад-
рес возврата
PC 8 Счетчик команд. Данный регистр содержит ад-
рес очередной команды, выбираемой для испол-
нения
SW 9 Слово состояния. Данный регистр содержит си-
стемную информацию, включая код условия
(СС — Conditional Code)
Форматы данных
Значения целого типа хранятся в виде 24-разрядного дво-
ичного числа. Для представления отрицательных чисел ис-
пользуется дополнительный код. Значения символьного типа
хранятся в 8-разрядном коде ASCII (см. приложение Ь).
Аппаратные средства для выполнения действий над числами
с плавающей точкой в стандартной модели УУМ отсутствую!.
Форматы команд
Все машинные команды стандартной модели УУМ имеют
следующий 24-разрядный формат:
______в_________1___________15_____________
| код оперэции(ор)|х| адрес(addi)|
Признак х используется для задания индексною сносе -1
сации.
Способы адресации
Имеются два способа адресации. В команде они задаются
разрядом х. Правила вычисления целевого адреса (target
address) по адресу, заданному в команде, описываются ниже-
следующей таблицей. (Скобки используются для указания на
содержимое регистра или ячейки оперативной памяти; напри-
мер, (X) обозначает содержимое регистра X.)
Способ Признак Вычисление
адресации адресации целевого адреса
Прямая
Индексная
ТЛ = addr
ТА = addr 4- (X)
Система команд
Для решения большинства простых задач вполне достаточно
базового набора команд УУМ. Он включает команды загрузки
регистра и записи его содержимого в память (LDA, LDX, STA,
STX и т. п.), а также команды целочисленной арифметики
(ADD, SUB, MUL, DIV). Все арифметические команды выпол-
няются над содержимым сумматора и содержимым слова опе-
ративной памяти. Результат остается в сумматоре. Специальная
команда (СОМР—СОМРаге) служит для сравнения значения,
содержащегося в сумматоре, со значением, хранимым в слове,
оперативной памяти. Эта команда устанавливает код условия
СС, являющийся признаком результата сравнения (<, >).
Команды условного перехода (JLT, JEQ, JGT) проверяют
установленное значение СС и выполняют соответствующую пе-
редачу управления. Две команды предназначены для организа-
ции взаимодействия подпрограмм: JSUB — переход на подпро-
грамму с занесением адреса возврата в регистр L; RSUB —
возврат по адресу, содержащемуся в регистре L.
В приложении А приведен полный список всех команд УУ. v
и УУМ/ДС с указанием их кодов и описанием выполняемых
функций.
Средства ввода-вывода
В стандартной модели УУМ ввод и вывод выполняются по
байтно. Для обмена используется самый правый байт м
тора. Каждому внешнему устройству присвоен уникальный
8-разрядный код. Существует три команды ввода-вывода. 1x1
дая из этих команд в качестве своего операнда задаст к>
устройства. I
Команда проверки состояния устройства (TD — Test Dc\k<
проверяет, готово ли требуемое устройство передать или п|’
пять очередной байт данных. Для индикации результата Щ
перки используется код условия q
указывает на готовность устройства КОда Условия «<»
означает, что устройство занято зняц? Мену; значение Л»
данное устройство неисправно или не пЛ °* Озна,1ает. что
Программа, желающая выполнить обмен S°4eH0 к Машине.
лор, пока устройство не будет готово и то |“Л'1а ждать
может выполнить команду чтения да иныхSn^n Этого она
или команду записи данных (WD - Write n ?-Read Dab)
рис. 2Л (гл. 2), п/л.острируе?6^
1.3.2. Структура УУМ/ДС
Память
nnaCvPVMyPn ПаМЯТИ УУМ/ДС аналогична описанной ранее
\мт\л/гг/- ' Одиако максимальный объем памяти доступной в
УУМ/ДС составляет 1 Мбайт (22° байт). Такое увеличение
требует изменения формата команд и способов адресации.
Регистры
Дополнительные регистры УУМ/ДС приведены в следующей
таблице:
Имя Номер
Назначение
В 3
S 4
Т 5
F 6
Базовый регистр. Используется для
адресации
Общий рабочий регистр. Специаль-
ного назначения не имеет
То же
Сумматор с плавающей точкой
(48 разрядов)
Форматы данных
Наряду с форматами данных, которые есть в стандартной
модели, УУМ/ДС предоставляет дополнительный формат для
Данных с плавающей точкой:
мантисса
порядок
Мантисса интерпретируется как число между
предполагается, что двоичная точка сто' ых чисел стар-
ред ее старшим разрядом. Для норма инице.' Порядок ин-
ший разряд мантиссы должен равняться д а в диапазоне от
териретируется как двоичное целое без
значе-
как
о до 2047. Если порядок имеет значение е я
"НеЛ’, ^,_!„б.С°ЛЮТНаЯ пел|,,ина числа буАет представлена
чеиия "разряда ^0'°^ ТочкоП Указыва”ся с помощью зна-
1ения разряда s (0 — положительное число, 1 — отпинателм t
число). Машинным нуль представляется в виде слова" соде «а
щего нули во всех разрядах. ’ содержа-
Форматы команд
Большой объем оперативной памяти, доступный в УУМ/ДС
означает что в общем случае 15-разрядиого поля для задания
адреса будет недостаточно. Таким образом, формат команд
стандартной модели УУМ не подходит для УУМ/ДС. Сущест-
вует два способа решения этой проблемы: либо использовать
относительную адресацию, либо расширять адресное поле до
20 разрядов. Оба эти способа используются в УУМ/ДС (см.
форматы 3 и 4 в нижеследующем описании). Кроме того, в
УУМ/ДС имеются команды, которые вообще не ссылаются на
оперативную память. Для этих команд используются форматы
1 и 2.
Ниже приведены форматы команд УУМ/ДС. Значения раз-
рядов-признаков в форматах 3 и 4 будут рассмотрены при об-
суждении способов адресации. Разряд е используется для того,
чтобы различать форматы 3 и 4 (е = 0 — формат 3, е = 1 —
формат 4). В приложении А для каждой команды УУМ/ДС
указан номер ее формата.
Формат 1 (1 байт):
8
код операции (ор)
Формат 2 (2 байт).
________8 4 4
код операции(ор) rl
Формат 3 (3 байт):
_________6 А*.1.1.1.1,____________12
код операции(opj|n|i|x|b|p|e| смещение (disp)
Формат 4 (4 байт):
Способы адресации ~ ------——
По сравнению со стандаптип”
зовапы два новых способа относптм°ю,^1-Ь'0 в УУМ/ДС реали
рых используются командный формат 3 ДЛ₽есац1“1. для кото-
следующей таблицей: 1 Их сУть описывается
Способ
адресации
Признаки
адресации
Вычисление
целевого адреса
Относительно
базы
Относительно
счетчика
команд
Ь = 1
Р = 0
6 = 0
р = 1
ТА (В) 4- disp (0 < disp 4095)
ТА = (PC) + disp (-2048 < disp < 2047)
Для способа адресации относительно базы поле смещения в
командном формате 3 интерпретируется как 12-разрядное целое
без знака. Для способа адресации относительно счетчика
команд это поле интерпретируется как 12-разрядное целое со
знаком, причем отрицательные величины представляются в до-
полнительном коде.
Если в командном формате 3 разряды b и р одновременно
установлены в 0, то в качестве целевого адреса используется
значение поля disp. Для командного формата 4 разряды b и
р должны оба равняться нулю, а целевой адрес берется из
поля адреса команды. Мы будем называть такой способ пря-
мой адресацией в отличие от относительной адресации, описан-
ной выше.
Каждый из этих способов адресации может соче-
таться с индексированием адреса. Признаком индексирования
является значение разряда к, равное 1 , и в этом случае
выражение для вычисления целевого адреса содержит допол-
нительное слагаемое (X). Заметим, что стандартная модель
УУМ использует только прямую адресацию (с индексированном
или без него). л
Разряды i и п в форматах 3 и 4 определяют спосо .
зования целевого адреса. Если i = 1, а п — 0- то с без
чение целевого адреса используется в качест в ₽ т ную
выполнения каких-либо дополнительных ссыл ' \епосоед-
память. Такой способ задания операнда назыв слова
ственной адресацией. Если i = 0, a п= 1, то содержимое слова
ПО целевому адресу используется в качес^® ДдрЕслн разряды
Такой способ называется косвенной адресац • местона-
i и п оба равны 0 или 1, то целевой ^*^6 простой
хождение операнда. Мы будем называть «. v
адресацией. При использовании непосредственной и косвенной
адресации использование индексирования невозможно.
Многие авторы используют термин исполнительный адрес
'effective address) для обозначения того, что мы назвали цс-
•
• *
а
3030 003600
• *
* ♦
•
Обоо 103000
» л
• •
♦ _ •
л ♦
• •
<5390 ООСЗОЗ
• ♦
•
•
«• 4
л 4
• •
сзоз 003030
• ♦
л» 4
• 4
• 4
(в)» ооеооо левым адресом команды. Однако име-
(pq » оозооо ется определенное противоречие, ко-
(X) о оооо&о гда теР**ин «исполнительный адрес»
употребляется для команд, использу-
ющих косвенную адресацию. Для то-
го чтобы избежать путаницы, мы в
данной книге используем термин «це-
левой адрес».
Команды УУМ/ДС, в которых не
используется непосредственная или
косвенная адресации, переводятся
ассемблером в машинные коды, име-
ющие в разрядах i и п значение 1.
Ассемблер стандартной модели УУМ
устанавливает в этих разрядах нуле-
вые значения (так как 8-разрядный
код операций всех команд стандарт-
ной модели заканчивается кодом 00).
В УУМ/ДС предусмотрены специаль-
ные аппаратные средства для обеспе-
чения упомянутой ранее совместимо-
сти «снизу вверх». Если оба разряда
i и п имеют нулевое значение, то
а
Машинная команда Значение, загружаемо в регистр А
Жстнадца- ^Теричное Двоичное 1 Целевой адрес
ор п i X ь Р е 1 смещение/адрес
<>32600 000000 1 1 0 0 1 0 оно 0000 0000 <3600 103000
фзсзоо 000000 1 1 1 1 О 0 ООН Оооо 000Q 6390 ООСЗОЗ
C2203Q 000000 1 0 0 0 1 0 0000 0011 ОООО 3030 103000
(H0030 000000 0 1 0 0 0 0 оооо ООП оооо 30 000030
Цозбоо оооооо 0 0 0 0 1 1 оно оооо оооо 3600 103000
0JJQC303 оооооо 1 1 0 0 0 1 0000 1JL0Q 0011 0000 0011 СЗОЗ 003030
Рис.
б
1.1. Примеры команд и способов адресации УУМ/ДС.
разряды Ь, р, е рассматриваются как часть поля адреса (а нс
как признаки способа адресации). Таким образом, командный
формат 3 становится идентичным командному формату, koi <’
рый используется в стандартной модели УУМ, что и обеспс’Ч
вает требуемую совместимость. с.
На рис. 1.1 приведены примеры различных способов адр
сации, которые обеспечиваются УУМ/ДС. На рис. 1.1а пока
но содержимое регистров В, PC и X, а также некоторых спе-
циально подобранных ячеек оперативной памяти. Значения при-
ведены в шестнадцатеричном виде. Машинный код команды
загрузки сумматора, ее целевой адрес и загружаемое значение
показаны на рис. 1.16. Вам следует тщательно изучить эти при-
меры и убедиться в том, что вы правильно понимаете различ-
ные способы адресации.
В приложении А дается полное описание всех форматов
команд и способов адресации, используемых в УММ/ДС.
Система команд
УУМ/ДС обеспечивает выполнение всех команд стандартной
модели. Дополнительно введены команды загрузки и запомина-
ния содержимого новых регистров (LDB, STB и др.), а также
команды арифметики с плавающей точкой (ADDF, SUBF,
MULF, DIVF). Имеются команды, использующие в качестве
операндов значения регистров. К ним наряду с командой пере-
сылки содержимого одного регистра в другой регистр (RMO)'
относятся арифметические команды, выполняющие действия над
содержимым регистров (ADDR, SUBR, MULR, DIVR). Кроме
того, введена специальная команда для обращения к суперви-
зору (SVC). Выполнение этой команды вызывает прерывание,
которое может быть использовано для связи с операционной
системой. Подробно организация обращений к супервизору и
прерывания будут обсуждаться в гл. 6.
Имеются и другие дополнительные команды. Полный список
всех команд УУМ/ДС с указанием их кода операции и выпол-
няемых функций приведен в приложении А.
Средства ввода-вывода
Команды ввода-вывода, рассмотренные нами для стандарт-
ной модели, выполняются и на УУМ/ДС. Кроме того, данная
модель имеет каналы ввода-вывода, которые могут работать
независимо от центрального процессора. Это позволяет совме-
стить операции обмена с процессом вычислений и тем самым
повысить общую эффективность системы. Для начала (start),
проверки (test) и прекращения (halt) канальных операции
обмена используются соответственно команды SIO, TIO и H1U.
Более детально эти вопросы будут обсуждаться в гл. 6.
1.4. Структура System/370
В этом разделе дается краткое введение в System/370. Sy-
stem/370 представляет собой скорее архитектуру, нежели кон
кретную ЭВМ. Эта архитектура, реализованая на ряде раз-
личных машин, представляет модели семейства 370. Хо1Я эти
модели различаются в аппаратной части и по другим физиче
скнм характеристикам, они логически совместимы друг с adv
гом. Любая программа должна дать одинаковые результаты на
любой ЭВМ семейства 370 при условии, что ее выполнение не
связано с временными или другими машинно-зависимыми ха-
рактеристиками. Архитектура System/370 совместима снизу
вверх с машинами System/360, т. е. программы для System/360
должны правильно выполняться на ЭВМ System/370 (при вы-
шеназванных условиях). Весьма похожие архитектуры были
реализованы на некоторых других процессорах фирмы IBM и
процессорах других фирм.
В этом разделе приводятся основные сведения, которые не-
обходимы, чтобы понять примеры программного обеспечения
System/370, обсуждаемые в дальнейшем. Дополнительную ин-
формацию можно найти в IBM [1983] и Страбл [1983].
Память
Память состоит из 8-разрядных байтов; каждый байт имеет
уникальный адрес. Группа из последовательных 2 байт, первый
из которых имеет адрес, кратный 2, называется полусловом.
Аналогично группа из последовательных 4 байт, начинающаяся
с адреса, кратного 4, называется словом, а группа из 8 байт,
начинающаяся с адреса, кратного 8,— двойным словом. Таким
образом, полуслово имеет длину 16 разрядов, слово — 32 и
Рис. 1.2. Деление памяти System/370 на байты, полуслова, слова и двой-
ные слова.
двойное слово — 64 разряда. Рис. 1.2 иллюстрирует такое раз-
деление памяти на байты, полуслова, слова и двойные слова.
Машинные команды должны быть обязательно выравнены
по границе полуслова (т. е. должны начинаться с адрес”11’
кратных 2). В большинстве случаев операнды команд моы*
располагаться в памяти с любого адреса. Например, 16-разр’1
иый операнд в команде АН (Add Halfword) может начинал
с любого места, т. е. он не должен выравниваться по грании”
полуслова. Однако скорость выполнения команд значпн'.н
выше, если операнды выравнены по границам, соответствуй’11’
их длинам. Максимальный объем оперативной цамяти, кон’|
обычно доступен в System/370, составляет 16 Мбайт (-г‘0:111' •
Регистры
В System/370 имеется 16 регистров обтпргл тмо
нумерованных от 0 до 15. Для их обозначения часто по^’/Р'”
ся символическими именами вида RO Ris к! ™ пользуют-
состоит из 32 разрядов. Для некоторых’ KOMa^^nXS
тельных регистра составляют один логический 64-разммый
операнд. Каждый регистр общего назначения может мпользо-
ваться в качестве сумматора в арифметических и логических
операциях. Кроме того, все эти регистры, за исключением R0
могут использоваться как базовые или индексные регистры
Имеется еще четыре других регистра, которые используются
для операций с плавающей точкой. Каждый из этих регистров
состоит из 64 разрядов. Некоторые команды используют два
таких последовательных регистра для хранения 128-разрядных
величин с плавающей точкой.
Все упомянутые выше регистры доступны в прикладных про-
граммах. В дополнение к ним есть 16 управляющих регистров,
которыми пользуется операционная система. Существует также
специальный регистр PSW (Program Status Word), содержа-
щий различную системную информацию (счетчик команд, код
условия и т. п.).
Форматы данных
System/370 обеспечивает хранение двоичных и десятичных
целых, величин с плавающей точкой и символов. Символы хра-
нятся в 8-разрядном коде EBCDIC. Двоичное целое хранится
как 16-разрядная (полуслово) или 32-разрядная (слово) дво-
. В зависимости от команды эти величины мо-
ичная величина
гут рассматриваться как целое со знаком или целое без знака.
Для представления отрицательных целых со знаком использу-
ется дополнительный код. лагатпи-
Десятичные целые представляются либо в зонном о .
ном формате, либо в упакованном десятичном форм1•
В любом случае представление имеет переменную Д1И,2'
ло используемых байтов выбирается программистом и <
от величины максимального хранимого числа. В '
тнчном формате четыре младших разряда ка^Д о до 9).
Держат двоичное представление десятичных ш4Ра1(очением по-
Четыре старших разряда каждого’ баШестнадцатеричное F).
следнего, обычно содержат код 1111 (ш ! десятичного
В этом случае представление в виде ифр в коде
формата совпадает с представлением де байта могутин-
EBCDIC. Четыре старших разряда последнего байта м >
'Третироваться как знак. Обычно для поло.мпельн*
эти разряды содержат шестнадцатеричиь . ’е рассматрн-
тельныхКОД D и для целых без знака (которые j
ваются как положительные) — код F. Например, десятичное
целое -f-53 842 представляется в зонном десятичном формате
как шестнадцатеричное F5F3F8F4C2 (5 байт), а—6071 — как
F6F0F7D1 (4 байт). В упакованном десятичном формате каж-
дый байт делится на два 4-разрядных поля. Во всех байтах,
за исключением последнего, каждое из этих полей содержит
двоичное представление десятичной цифры. В каждом байте
первое поле содержит десятичную цифру, а второе — знак (по
схеме, описанной выше). Таким образом, десятичное целое
'4-53 842 представляется в упакованном десятичном формате как
шестнадцатеричное 53 842С (3 байт), а — 6071 —как 06071D
(3 байт).
Величины с плавающей точкой представляются в одном из
следующих форматов:
Короткий формат (слово):
24
f
Длинный формат (двойное слово):
S6
Расширенный формат (два последовательных двойных ело
В любом случае величина числа представляется с помощью
мантиссы f и порядка е. Порядок интерпретируется как двоич-
как шестнадцатеричное без
ное целое без знака. Мантисса— -upht не-
знака, у которого «шестнадцатеричная точка» расположу с
посредственно перед самой левой шестнадцатеричной I
В нормализованных числах с плавающей точкой стаР 1110Г0
стнадцатеричная цифра отлична от нуля. Для раиш [
формата с плавающей точкой порядок е формируется ‘ а.
катенация порядков el и е2, а мантисса f —как КОН
ния [I и f2. Абсолютная величина представляемою таю.
разом числа равна
f * 16<‘-в4>
1.4. Структура Systcm/370
25
ПОЛОЖИ-
Знак числа определяется значением разряда s (0 — положи-
тельное, 1 — отрицательное). Число нуль представляется кодом,
содержащим нули во всех разрядах.
Отметим, что порядок чисел с плавающей точкой в Sy-
stem/370 интерпретируется как степень 16 (а не 2, как в боль-
шинстве машин). Это сделано для того, чтобы увеличить поря-
док чисел, которые могут быть представлены с помощью одно-
го 32-разрядного слова. Поэтому мантиссу следует интерпрети-
ровать как шестнадцатеричное (а не двоичное) число. Это
част, что три старших разряда мантиссы могут равняться
(если старшая шестнадцатеричная цифра равна 1). В
этого количество значащих разрядов в мантиссе может
озиа-
нулю
силу
быть
различным в зависимости от величины числа.
Форматы команд
В System/370 имеется восемь основных форматов команд.
В этом разделе мы кратко остановимся на трех наиболее об-
щих из них. Детальное описание всех восьми форматов можно
найти в IBM 11983].
У большинства команд System/370 есть два операнда. Для
этих команд существуют три возможных варианта расположе-
ния операндов в памяти: оба операнда в регистрах; один в ре-
гистре, другой в памяти; оба в памяти. Следующие форматы
команд являются типичными для каждого из этих случаев.
Формат RR:
8 4 4
ор г1 г2
8 4 4 4 12
Формат RX:
г1 х2 Ь2
Формат SS:
8 4 4 4 12 4 12
В формате RR оба операнда точкой.Р Номер
шего назначения, либо в регистрах с jlin рег11СТра
регистра кодируется в команде <“ак формата RX один
определяется кодом операции. Дл> 1 ой_________в оперативном
операнд находится в регистре п, / * svslem/370 требуется
памяти. Для задания полного адреса у занима*
24 разряда. Для того чтобы уменьшить объем
смый командой, исполнительный адрес (в общем случае) за-
дается с помощью базового регистра Ь2, индексного регистра
х2 и 12-разрядного смещения d2. (Порядок вычисления целево-
го адреса для каждого способа адресации будет описан ниже.)
В формате SS оба операнда расположены в памяти. Если
команда данного типа ссылается на операнды переменной дли-
ны, то длина операндов задается в команде с помощью полей
11 и 12. Адреса операндов определяются с помощью базового
регистра и смещения. Использование индексного регистра за-
прещено.
В некоторых других форматах команд поле кода операции
расширено до 16 разрядов (форматы RRE и SSE). Формат RX.
можно изменить так, чтобы разрешить использование второго
регистрового операнда вместо индексного регистра (формат RS)
или чтобы включить 8-разрядный непосредственный операнд
вместо двух номеров регистров (формат SI). Одна из модифи-
каций формата SS определяет 8-разрядный код, который ис-
пользуется в обоих операндах. Другая модификация имеет
только один операнд.
Способы адресации
В System/370 команды, которые ссылаются на операнды,
расположенные в оперативной памяти, должны использовать
относительную адресацию с базированием. Целевой адрес по-
лучается как сумма содержимого базового регистра, индексного
регистра (если он задан) и смещения. Смещение интерпретиру-
ется как 12-разрядное целое без знака (отрицательное смеще-
ние запрещено). Регистр общего назначения R0 нельзя исполь-
зовать как базовый или индексный регистр. Если в команде
задан в качестве базового или индексного регистра регистр с
номером нуль, то при вычислении целевого адреса соответству-
ющий регистр использоваться не будет. В System/370 применя-
ются два способа непосредственной адресации. В команде LA
(Load Address) целевой адрес загружается в заданный регистр
(вместо того чтобы вызывать операнд из оперативной памяти).
Некоторые другие команды, например такие, как MVI (Мо\ е
Immediate), используют непосредственый однобайтовыи опе-
ранд прямо из команды. Однако это особые случаи, когда не-
посредственная адресация определяется как часть команда
В большинстве команд использование непосредственных о
рандов невозможно.
В System/370 не предусмотрено адресации относительно
счетчика команд или косвенной адресации. Прямая адресапи.
возможна только в весьма специфическом случае, когда в ка
честве и базового, и индексного регистров используется регистр
с нулевым номером. В этом случае в качестве фактической’
адреса будет взято 12-разрядное смещение. Возможность пр 1
5^—--------------------- СтРУктУРа System/370
мой адресации первых 4096 б!йГ7Г"^ ------------------------
используется в операционной системе^,ра„тивной памяти иногда
имущества. еме и дает определенные пре.
Система команд
Команды System/370 делятся на Па
значения, десятичной арифметики аои^₽ЛаССОВ: общего на-
точкой, управляющие и ввода-вывод'. м!Т"КИ С Плввающей
навливают 4-разрядный код условия для hhJ- К°Маидь1 уста'
ситуации. Команды условного переход! ^ А ации Различных
новленныи код и выполнить соответствуют^ Пр°вер1,ть Уста-
ныи список команд System/370 с vuJoZ Щ ветвление. Пол-
пми кодов условия можно найти в IBM ИОЯ-й устанавливасмых
К командам общего назначения относятся —
ки и запоминания регистров общего назпачетт АЫ ЗЭГру3’
команды, обеспечивающие выполнение двоичных In Также
ских операций и операций сравнения. Каждая из этих фтатий
может выполняться с помощью нескольких различных ко™
в зависимости от типа и месторасположения щпользуемых one
рандов. Например, двоичное сложение выполняется следующи-
ми машинными командами:
А сложение слова, память — регистр;
АН сложение полуслова, память — регистр;
AL сложение слова, без знака, память — регистр;
ALR сложение слова, без знака, регистр — регистр;
AR сложение слова, регистр — регистр.
команд общего назначения относятся также команды
К группе
команды пересьшси^даппьп переходов, логические операции,
stem/370 имеется кп!!!Л « МИ0Г11е Другие операции. В Sy-
похожая ня Яня™ манДа обращения к супервизору (SVC),
жая на аналогичную команду УУМ/ДС.
ДлЯ ВЫППпиа,Ill ГТ "'I г г г ] - ' использованы
Кован^Д? Я аРиФметических операций над целыми в упа-
ДДя J‘ десятичном формате. Кроме того, имеются команды
gfafi Ре°орззования зонного десятичного формата в упакован-
ды И “аобоРот (команды РАСК и UNPACK) , а также коман-
&7*,пРе°бразования двоичного целого в упакованный десятич-
Ком (р0Рмат и обратно (команды CVD и CVB). Две другие
иь аНД,Ы пРедоставля,от возможности для редактирования дан-
К’Х, выполняя, например, такие операции, как вставка запятой
Десятичной точки в числовые величины.
_ команды арифметики с плавающей точкой используются для
полпенни операций над числами с плавающей точкой (за-
РУзка и запоминание регистров с плавающей точкой, арифме
лА.Ческие операции и операции сравнения). Гак же как 1
У'<ае команд общего назначения, код операции за с
типа и месторасположения операндов. Например, группа
команд сложения включает следующие команды:
AD сложение с нормализацией, длинный формат,
память — регистр;
ADR сложение с нормализацией, длинный формат,
регистр — регистр;
АЕ сложение с нормализацией, короткий формат,
память — регистр;
AER сложение с нормализацией, короткий формат,
регистр — регистр;
AU сложение без нормализации, короткий формат,
память — регистр;
AUR сложение без нормализации, короткий формат,
регистр — регистр;
AW сложение без нормализации, длинный формат,
память — регистр;
AWR сложение без нормализации, длинный формат,
регистр — регистр;
AXR сложение с нормализацией, расширенный формат,
регистр — регистр.
В группу команд управления входят привилегированные
команды, предназначенные главным образом для использования
в операционной системе. К ним относятся команды для загруз-
ки и запоминания PSW и управляющих регистров, команды
защиты памяти и многие другие. Некоторые функции, выпол-
няемые этими командами, мы рассмотрим при обсуждении опе-
рационных систем в гл. 6.
Средства ввода-вывода
В System/370 обмен с внешними устройствами осуществля-
ется с помощью каналов ввода-вывода, похожих на те, что
были описаны для УУМ/ДС. Команды ввода-вывода позволяют
центральному процессору (ЦП) начать, остановить и проверить
каналы, а также выполнить другие управляющие операции.
Имеется, кроме того, возможность, позволяющая ЦП выпол-
нять прямую побайтную передачу с помощью специального ин-
терфейса, не зависящего от каналов.
1.5. Структура ЭВМ VAX
Семейство ЭВМ viv х.
1978 г. Аббревиатура vaу 0 "РВД^авлено фирмой DEC п
важных особенностей „Указывает на одну из наиболее
ресное расширение (ViHuaT уУгРЫ ~ виРтУальиое ад‘
дРУгие ЭВМ (включая Эузит^ЗУоГк. П5'°П2' Х°ТЯ МН0Г"С
у iem/d/0) были модифицированы для
5- Структура ЭВМ VAX
ПрСДОСТЗВЛСНПЯ B1IPTV3 ПВМпй по
чала проектировалась в расчете Т’ пСИСТема VAX с самого 11а
странство Виртуальная память позволяв?^"00 аДресное "Ро-
так, как будто они имеют доступ к "рограммам работ^
об?™а р^^й оПеХв±:яилй памятв» вне
зуемои в системе. Заботу об управлении пТ™ * Памя™’ вне-
операционная система. Мы обсутим вД ’'° бсрет ,,а себя
зи с изучением операционных систем в ™ r У’° Память Всвя'
При проектировании архитектуры ЭВМ х/ду г
смотрена совместимость с более паниим \АХ «б а прслУ’
PDP-11. Средства совместимости обеспёч Гы , ±?°М ЭВДХ
туры, что позволяет выполнять без каких ибо «X а’„1Пара’
гое программы PDP-11 „а ЭВМ VAX. Более toS See™ X-
можность одновременной работы в многопользовательском пе-
жиме программ для PDP-11 и VAX. >ьском рс
В этом разделе дается сводная информация о некоторых
основных характеристиках архитектуры ЭВМ VAX Допотни-
тельную информацию можно найти в DEC 11981Г и Бч .<•
1[1983]. 1 1
Память
Память ЭВМ VAX состоит из 8-разрядных байтов, каждый
из которых имеет свой адрес. Два последовательных байта со-
ставляют слово (word), четыре — длинное слово (longword),
восемь — квадрослово (quadword), шестнадцать — октослово
(octaword). Как и в System/370, для уменьшения времени до-
ступа к оперативной памяти желательно, чтобы слова, длинные
слова, квадрослова и октослова были выравнены по соответ-
ствующей границе.
Реальная оперативная память ЭВМ VAX может достигать
223 байт. В то же время все программы VAX работают в вир-
туальном адресном пространстве объемом 2 2 байт. Объем ре-
альной оперативной памяти обычно никак не влияет на вьпкю
пение прикладных программ. Половина виртуальною адресноп
пространства называется системным пространством. ([ J ‘
space). Эта часть содержит программы 0Г,еРа^10''1'с’11 Бовина
и используется совместно всеми программами. Д| > ‘ ппонес сов
адресного' пространства называется nPOCTP^^ttQ отдельно
[(process space). Пространство процессе в | ' ‘ содержит
Для каждой программы. ЧаСд З^Хты’со стеками имеются
стеки, доступные программе. Для р
специальные регистры и команды.
Регистры назначения, которые
В ЭВМ VAX есть .б^роо = >=о^е
обозначаются как RO — ммвия и
регистров имеют специальные
дого регистра общего назначения — 32 разряда. Регистр R15
используется как счетчик команд и имеет имя PC. Во время
выполнения команды его значение изменяется таким образом
чтобы всегда указывать на очередной обрабатываемый байт
команды. Регистр R14 используется в качестве указателя стека
(stack pointer) и именуется SP. Этот регистр указывает на
вершину стека данной программы в пространстве процессов.
Хотя для этой цели можно использовать и другие регистры,
однако в машинных командах, косвенно обращающихся к сте-
ку, всегда используется регистр SP. Регистр R13 используется
как указатель фрейма (frame pointer) и носит имя FP. Согла-
шение о связях между процедурами в ЭВМ VAX построено
на структуре данных, называемой стеком фреймов. При вызове
процедуры адрес фрейма в стеке фреймов помещается в ре-
гистр FP. Регистр R12 имеет имя АР и используется в каче-
стве указателя аргументов (argument pointer). В соответствии
с соглашением о связях при вызове процедуры этот регистр
используется для передачи адреса начала списка фактических
параметров.
У регистров R6 — R11 нет специального назначения, и они
могут использоваться в программах для обычных целей. Точно
так же можно использовать и регистры R0 — R5, но они, кро-
ме того, применяются специальным образом в некоторых
командах.
Кроме регистров общего назначения имеется регистр состоя-
ния процессора PSL (Processor Status Longword), который со-
держит переменные состояния и признаки, связанные с процес-
сом. Наряду со многими другими информационными полями
PSL содержит код условия и признак, указывающий на работу
процесса в режиме совместимости с PDP-11. Есть также ряд уп-
равляющих регистров, употребляемых для поддержания раз-
личных функций операционной системы,
форматы данных
Для хранения целых может использоваться байт, слово,
длинное слово, квадрослово и октослово. Отрицательные целые
величины хранятся в дополнительном коде. Для храпения сим-
вольных величин используется 8-разрядный код ASCII.
В системе VAX предусмотрены четыре различных форм ы
для хранения величин с плавающей точкой длиной от четырс
до шестнадцати байтов. Два из них совместимы с формам
ми PDP-11 и являются стандартными для всех процессор’-
семейства VAX. Два других являются дополнительными и 0
печивают хранение величин в более широком диапазоне за сче
дополнительных разрядов, используемых для представлен^
порядка числа. В любом случае форматы данных ЭВМ ' •'
принципиально не отличаются от форматов, рассмотренных Ра
нее. Величина числа с плавающей точкой ппрпрт,
М0‘пИчвм\МЛ'?еК"аЯ Иа соответствующую стетекь 2ЛЯ"'Я Ка“
В ЭВМ VAX предусмотрен упакованный десятичный а
аналогичный соответствующему формату System/370 Йм₽атТ’
также числовой формат в котором каждая цифра числа ЙшГ
сывается в отдельном байте. В этом смысле числовой
похож на зонный десятичный формат System/370. за исключ?
нием того что цифры хранятся в коде ASCII, а не в EBCDIC
Поэтому обычно старшие четыре разряда каждого байта К этом
формате имеют шестнадцатеричный код 3, а не F В то же
время числовой формат сложнее, чем зонный десятичный фор-
мат, так как знак числа может быть указан либо в последнем
байте (как и в System/370), либо в отдельном байте перед
первой цифрой. Эти две модификации называются соответствен-
но суффиксным числовым форматом (trailing numeric) и ра г-
дельным префиксным числовым форматом (leading separate
numeric).
В ЭВМ VAX обеспечиваются средства для работы с очере-
дями и строками битов переменной длины. Конечно, такие
структуры данных могут быть реализованы на любой машине,
однако в ЭВМ VAX для работы с ними предусмотрены специ-
альные аппаратные средства. Так, с помощью всего одной ма-
шинной команды можно включить или исключить элемент оче-
реди или выполнить различные операции над строкой битов.
Наличие столь мощных команд и сложных типов данных явля-
ется одним из наиболее необычных свойств архитектуры ЭВМ
VAX.
Форматы команд
В ЭВМ VAX используется формат команд переменной дли-
ны. Каждая команда состоит из кода операции (1 или 2 байт),
за которым в зависимости от типа операции следует до 6 спе-
цификаций операндов. Каждая спецификация операнда исполь-
зует один из способов адресации и задает некоторую дополни
тельную информацию для определения месторасположения oi с
ранда в памяти.
Способы адресации
В ЭВМ VAX предусмотрены РазнообР33йНЬ'е_ Сэ"°х°способов
сации. За небольшим исключением, Операнд мо-
здресации может использоваться в люоои ' тое ' либо по ад-
Жет задаваться либо непосредственно в Р Радается по ад-
ресу, находящемуся в регистре. J\CJI Рвь1П0ЛНения команды
Ресу, находящемуся в регистре, то ‘ увеличиваться или
Одержимое регистра может автом< рен0 несколько спо-
Умеиьшаться иа длину операнда Пр ДУ р х МОгут псполь-
«обов адресации относительно базы, в кои
MH
зонаться поля смещения различной длины. Если этот еп™ г
адресации используется с регистром PC, то мы получим спо
соб адресации относительно счетчика команд Кажлпй 5П0’
способов адресации может включать в себя индекХй репютп
а многие из них могут использоваться для определения кос’
венной адресации. Наконец, разрешены непосредственные опе-
ранды и различные способы адресации, предназначена
специальных целей. Дальнейшую
DEC [1981].
, ые для
информацию можно найти в
Система команд
Одной из целей разработчиков системы VAX было создание
системы команд, симметричной в отношении различных типов
данных. Значительная часть мнемонических имен команд фоп-
мируется с помощью комбинации следующих элементов:
— префикса, определяющего тип операции;
— суффикса, определяющего тип операндов;
— модификатора (в ряде команд), задающего число опе-
рандов.
Например, команда ADDW2 является операцией сложения с
двумя операндами, каждый из которых занимает длинное слово.
Аналогично команда MULL3 является операцией умножения с
тремя операндами, каждый из которых занимает одно слово.
Команда CVTWL определяет операцию преобразования слова
в длинное слово (в последнем случае подразумевается исполь-
зование двух операндов). В большинстве команд операнд мо-
жет располагаться в регистре, в памяти или непосредственно в
самой команде. Один и тот же код операции используется не-
зависимо от месторасположения операндов. Этот подход явля-
ется более гибким по сравнению с подходом в System/370, ко-
торый требует различных кодов операций в зависимости от
месторасположения операндов.
VAX обеспечивает все обычные типы команд для вычисле-
ний, пересылки данных, преобразования, сравнения, ветвления
и т. п. Кроме того, существует ряд более сложных команд, чем
те которые имеются в большинстве ЭВМ. Во множестве слу-
чаев такие операции являются аппаратной реализацией часто
используемых последовательностей команд для Увел"^И1'^
(Ьективности и скорости их выполнения. Например, VAX пред
ставляет команды групповой загрузки и запоминания реги Р >
а также команды для работы с очередями и строками битов
° ппипм Ппедусмотрены мощные команды для
переменной Длины 11 ' Рс помощью одной-единствеинои
зова и возврата из проц .р.п содержимого заданной
команды осуществляется - списка фактических параметров
,ру„пы Реги;Х’ ателями стека, фрейма и сп.ки
процедуре, управление
и списки
_____________________16- Структура ЭВМ CYBER
---------------------------------------——-------------------33
аргументов, а также установка маски мя пп
ошибок в арифметических операциях. Более де^лм^РаЩ?ия
мацию о системе команд VAX можно найти в DEC’
*-• I I УО I 1 ч
Средства ввода-вывода
Обмен в ЭВМ VAX выполняется с помощью контпппп
ввода-вывода. Каждый контроллер имеет набор регистре
стояния/управления и регистров данных, задающих нростпа '
ство в физической оперативной памяти. Участок адресного in
странства, на которое указывают регистры контроллера на и
вается пространством ввода-вывода. ’
Никаких специальных команд для обеспечения доступа ре-
гистров контроллера к пространству ввода-вывода не требует-
ся. Драйвер ввода-вывода выполняет команды контроллера за-
поминая значения в нужных регистрах, точно так же, как если
бы они были физическими областями памяти. Установление со-
ответствия между адресами в пространстве ввода-вывода и фи-
зическими регистрами устройства управления осуществляется
подпрограммой управления оперативной памятью.
1.6. Структура ЭВМ CYBER
В этом разделе мы рассмотрим архитектуру ЭВМ серий
CYBER 70 и CYBER 170 фирмы CDC. Несмотря на различия
моделей этих серий в аппаратной части, они совместимы на
уровне программ. Структура ЭВМ CYBER в значительной сте-
пени схожа с архитектурой ЭВМ серии CDC 6000 с некоторы-
ми дополнительными возможностями. Похожая архитектура
реализована в ЭВМ серии CYBER 180, объявленной фирмой
CDC в 1984 г. Эти машины имеют другую длину слова и зна-
чительные улучшения в аппаратной части, однако предусмат-
ривают возможность для работы в режиме CYBER /0 и CA-
BER 170. ‘
CYBER — это мультипроцессорная система. В ее состав вх"-
Дят центральный процессор (ЦП) и несколько периферийных
процессоров (ПП). Обычно ЦП занят обработкой |,ользова^'''
ских программ, в то время как ПП выполняют фуп^ни ‘
Нионной системы. ПП может начать или прерват > *
программы, осуществляемое ЦП, для выполнени» I • •
Функций. Каждый ПИ имеет доступ к оперативной п
и к устройствам ввода-вывода. Кроме того, к /.
свою собственную память, тщ н цп
Структура памяти, регистры и сист^‘ ‘ плугом. В то
абсолютно разные и никак не связаны д]. > :р'через обшую
время они могут обмениваться информйй.
2 Зак. 792
память. 13 этом рззделе мы коснемся лишь хзрзктсрнстик 11II
,11,жб!',уо«,1'',1форгмац'"° ° ,7ор,уЛтурах ЦП “ ПП мож"° "а*™
и CDC [1981а] и Гришман [1974].
Память
Память центрального процессора CYBER состоит из 60-раз-.
рядных слов. Машина имеет словную адресацию. К полям вну-
три слова нет средств прямого доступа, за исключением не-
большой группы команд, ориентированных на обработку сим-
вольной информации. Максимальный объем оперативной памяти
2561\ (218) слов.
Регистры
Программа пользователя может работать с тремя группами
регистров: А, В и X. В каждой группе имеется по восемь ре-
гистров, которые соответственно обозначаются АО — А7, ВО —
Б 7 и ХО —Х7. Длина регистров групп А и В — 18 разрядов.
Обычно регистры группы А используются для адресации, а ре-
гистры группы В — в качестве индексных регистров или для
хранения небольших целочисленных значений (например, счет-
чик цикла). Регистр ВО всегда содержит нулевой код. Длина
регистров группы X — 60 разрядов. Они используются при вы-
полнении большинства операций, а также для хранения вели-
чин, выбранных из оперативной памяти.
Между регистрами группы А и регистрами группы X уста-
новлено не совсем обычное соответствие. Если в регистр А1
заносится некоторое значение, то оно рассматривается как ад-
рес слова в оперативной памяти, и в регистр XI автоматически
заносится содержимое слова оперативной памяти по эюму ад-
ресу. Такое же логическое соответствие существует мсжд\
регистрами А2— А5 и регистрами Х2 — Х5. Если некоторый
адрес заносится в регистр Аб, то содержимое регистра Хо и1’ 1 '
матически записывается в оперативную память по этому^ адр<
су. Аналогичное соответствие установлено между регистра'
А7 и Х7. Регистры АО и ХО логически между собой не связаны.
Форматы данных
Целые величины хранятся в виде 60-разрядных да01'^1]>'Х
чисел (хотя некоторые операции целочисленной арпфм '
используют только младшие 48 разрядов словам Д-1Я .. ко1.
ставления отрицательных чисел используется °^Рат11Ь1Н
Символьная информация хранится в 6-разрядном
нии, которое называется дисплейным кодом CDC. Вс.к .в
использования 6-разрядного символьного кода содержимое . 0
иа ЭВМ CYBER обычно, представляется в виде восьмери <
(а не шестнадцатеричного) числа.
ЗБ
Числа с плавающей точкой представляются в следующем
формате: J
И
е
$
-48
С
Коэффициент с интерпретируется как дя „
целое. Предполагается, что двоичная точка пТДН0С АвончИое
средственно после младшего разряда коэ^ «^по-
мализованных чисел старший разряд коэйжт. та> Для »ор-
держать 1. Порядок е интерпретируется как iT’Ta Д0ЛЖС1‘ со-
ичное целое без знака. Абсолютная величина ц?Л3рЯАНое дво’
щей точкой может быть записана в виде а с плаваю’
с «. 2(е-1024)
Знак числа определяется разрядом s. Для положительных чи
сел он равен 0. Отрицательные числа представляются инверти-
рованием всех разрядов слова. Величина нуль с плавающей
точкой записывается в виде слова, имеющего нули во всех
60 разрядах.
Некоторые значения порядка зарезервированы и не исполь-
зуются для обычных чисел с плавающей точкой. Такие зарезер-
вированные значения порядка используются для представления
положительной и отрицательной бесконечности (результат де-
ления числа, отличного от нуля, на нуль) и для представления
положительной и отрицательной неопределенности (результат
деления нуля на нуль).
Форматы команд
Для большинства команд ЦП ЭВМ CYBER используются
следующие форматы:
к(15-разрядный формат);
6 ззз
op i J К
"(30-разрядный формат) :
6 3 з ________18
*
J
J
Ор
addr
.....—..-
® этих форматах ор является кодом операции. Регистры, ис-
пользуемые в качестве операндов, обозначены как i, j, k. Тип
Регистров определяется командой. Если один из операндов рас-
положен в оперативной памяти, то необходимо использовать
•^разрядный формат. Поле addr в этом формате содержит пол-
pifi 18-разрядный адрес.
Для некоторых команд поле кода операции логически
ширено до 9 разрядов за счет поля i. В других компип^ рас'
i и k составляют одно поле, в котором могут задаваться мяр^
НЛП величина сдвига. Кроме того, есть специальный 60 оазпя?
“ыи формат для небольшой группы команд, ориентипов п hi\v
на обработку символьной информации. Используемые в этом
формате поля различны для разны-х команд. Детальное опнст
вне этих форматов можно найти в CDC [1982а].
Способы адресации
В ЭВМ CYBER предусмотрен единственный способ адре-
сации. Для доступа к оперативной памяти необходимо поме-
стить полный 18-разрядный адрес в регистр группы Л, что
обеспечивает загрузку соответствующего регистра группы X
словом из оперативной памяти или запись его содержимого в
память. Поскольку используются реальные адреса оперативной
памяти, то этот процесс во многом похож на способ прямой
адресации, который мы обсуждали ранее. Однако команда
установки регистра Л может также выполнять вычисления,
включающие до трех операндов. Поэтому программист может
реализовать широкий набор различных способов вычисления
целевого адреса, включая способы, эквивалентные косвенной и
индексной адресации, а также адресации относительно базы.
Кроме того, предусмотрены средства для непосредственней
адресации.
Система команд
Логически команды ЦП CYBER распадаются на несколько
групп Самая большая и наиболее часто используемая соде,-
жпт команды установки регистров А, В и X. Иллюстрацией не-
которых из возможных команд этой группы могут служить с.
дующие команды:
SAi Aj 4- Bk
SAi адрес
SBi Bj + K
SXi Xj + Bk
Так, например, команда
SA3 A4 4-B1
помещает в регистр
В свою очередь это
слова оперативной
Команда
АЗ сумму содержимого Рег^тР°“>рж
вызовет загрузку регистра ХЗ содерл д.,
памяти по адресу, занесен • .
SA6 ВЕТЛ
I 6. Структура ЭВМ CYBER
37
значения
_ в регистр
содержимого Х6 по этому
аносить иноил'"--
(где ВЕТА— это мет ------------
адрес в оперативной памяХ^ в качестве своего
Д6, что обеспечивает запомннапирИТ Значен»е ВЕТА
адресу. Команды установки могут\яС°Аерж
любой группы (А, В или XI ,, У заносить значение „
для задания своих операндов ИМеЮт Различные возмож?"1’
Команды установки выполняют .. °озможност„
ными величинами, даже ее™ /Л Счисления нал is п
группы X. Существует другаяУ труХ* №мГ'ЗВ°ДПТСЯ »
чивает выполнение сложения и вычитания V0T0Pa" °6<Х
лых, арифметику с плавающей точкой Д «-разрядных
операции над X регистрами. Кроме того " л°™чесК110
предназначенные для работы с символами сеТЬ,ре K0Mai«'i.
команд можно осуществить пересылку стопи 5 этих
”Т ЭвТсуВР»ВЬ'П0Л"ИТЬ "«"«вольте “X. °"Сра-
Ь ЭВМ CYBER предусмотрены команд равиение строк,
рехода и два типа команд условного перехода Ком.°ВНОГО пс-
го типа проверяют значение, содержащееся „К°ма,|ды
осуществляют передачу управлещ,яР в Х.симост CT₽tX’ "
тата. Команды второго типа обеспечивают переда^ ynpaS,
В зависимости от результата сравнения содержимого двух ре-
гистров группы В. Понятия код условия в ЭВМ CYBER нет.
Сравнение и передача управления осуществляются одной
командой. Предусмотрена специальная команда передачи уп-
равления с возвратом для вызова подпрограмм. Адрес возврата
хранится в памяти в первой команде вызываемой подпро-
граммы.
Средства ввода-вывода
Все операции обмена выполняются периферийными процес-
сорами. Как это делается, а также некоторые другие общие во-
просы взаимодействия между ЦП и ПП мы обсудим в гл, 6,
Глава 2. Ассемблеры
В этой главе будут рассмотрены вопросы проектирования и
реализации ассемблеров. Существует целый ряд основных фу„, ’
ций, например таких, как трансляция мнемонических кодов
операции в их эквиваленты на машинном языке или присваи-
вание машинных адресов символическим меткам, которые долж-
ны выполняться любым ассемблером. Если мы будем рассмат
ривать эти основные функции, то большинство ассемблеров
окажутся весьма похожими. '
Однако за пределами этого базового уровня возможности
предоставляемые ассемблерами, а также схемы их построения
сильно зависят как от входного языка, так и от языка маши-
ны. Одним из аспектов такой машинной зависимости, естествен-
но, являются имеющиеся различия в форматах машинных
команд и кодах операций. Как мы увидим в дальнейшем, суще-
ствуют и менее явные зависимости между ассемблерами и ар-
хитектурой ЭВМ. С другой стороны, некоторые средства языка
ассемблера (и соответствующих ассемблеров) не имеют прямой
связи со структурой машины. Их выбор является в известном
смысле произвольным и определяется разработчиком языка ас-
семблера.
Вначале мы рассмотрим базовый! ассемблер для стандартной
модели нашей упрощенной учебной машины. В разд. 2.1 рас-
сматриваются наиболее важные операции, выполняемые типо-
вым ассемблером, и описываются общие методы их реализации.
Приведенные здесь алгоритмы, структуры данных и др. ис-
пользуются в большинстве ассемблеров. Таким образом, дан-
ный уровень описания дает нам отправную точку для изучения
более сложных средств, предоставляемых ассемблерами. Мы
также можем использовать эту базовую структуру как каркас
при разработке нового ассемблера.
В разд. 2.2 мы изучим некоторые типичные расширения оа-
зовой структуры, которые диктуются аппаратными особенностя-
ми. Это будет сделано на примере ассемблера для УУМ/.-1
Конечно, ассемблер УУМ/ДС не покрывает все возможные ма-
шинно-зависимые свойства, однако он включает некоторые сред
ства, которые наиболее часто встречаются в реальных маш’1
нах. Рассматриваемые здесь принципы и технические прием
могут быть легко применены к другим ЭВМ.
В разд. 2.3 обсуждаются наиболее часто встречающиеся у
шинно-независимые расширения языка ассемблера и спосо*
to
их реализации. Опять-таки нашей целью является не рассмо-
трение всех возможных вариантов, а обсуждение концепций и
технических приемов, которые могут быть использованы при
разработке нового ассемблера.
В разд. 2.4 обсуждаются некоторые важные варианты схем
ассемблирования. Схема ассемблирования относится к тем ха-
рактеристикам ассемблера, которые не находят своего отраже-
в самом языке ассемблера. Мы рассмотрим однопросмот-
пйые и многопросмотровые ассемблеры, а также двухпросмот-
лвые ассемблеры с оверлейной структурой. Мы также коснем-
я вопросов реализации таких ассемблеров и обсудим ситуации,
в которых они могут быть полезны.
Наконец, в разд. 2.5 будут вкпатпп то
примеры ассемблеров для реальных машин" Мы
мяться к детальному обсуждению всех аспектов rS. стрс‘
мы концентрируем наше внимание на наиболее^?™ ”°ro
возможностях, которые являются следствиями тех и ,?Т,ЫХ
аппаратных или программных решений. х
2.1. Основные функции ассемблера
На рис. 2.1 приведена программа на языке ассемблера ба-
зовой модели УУМ. Различные варианты этой программы мы
будем использовать на протяжении всей этой главы для иллю-
страции различных свойств ассемблера. Номера строк исполь-
зуются только для ссылок и не являются частью программы.
Эти номера помогают также установить соответствие между
участками различных вариантов программы. Мнемонические
имена команд, используемые в примере, были рассмотрены в
разд. 1.3.1 и приведены в приложении А. Модификатор, «,Х»,
следующий за операндом (см. строку 160), указывает на исполь-
зование индексной адресации. Строки, начинающиеся с •, явля-
ются комментариями.
Кроме мнемонических имен машинных команд в примере
использованы следующие директивы ассемблера:
Определяет имя и начальный адрес программы.
Указывает на конец исходной программы и (обыч-
но) задает первую исполняемую команду про-
START
END
BYTE
WORD
RES В
RESW
Пирует символьную или
константу, занимающую сто антЫ
необходимо «ед=ия конст,од„о
Формирует
слово.
Резервирует
ных.
Резервирует
заданное количество бантов для даи-
заданное количество слов для данных.
\к
Гтрока Исходное предложение
5 10 15 20 25 COPY FIRST CL OOP START STL JSUB J000 RETADR RDREC КОПИРОВАНИЕ ФАЙЛА СОХРАНЕНИЕ АДРЕСА ВОЗВРАТА ввод входной ЗАПИСИ
LDA COMP LENGTH ZERO ПРОВЕРКА НА EOF (LENGTH = 0>
30 35 40 JEQ if* I 11^ ENDFIL ВЫХОД, ЕСЛИ НАШЛИ EOF
j. >uh J WRREC CLOOP вывод выходной ЗАПИСИ никл
45 50 ENDFIL LDA STA EOF buffer ЗАНЕСЕНИЕ МАРКЕРА КОНЦА ФАЙДА
55 40 LDA STA THREE LENGTH УСТАНОВИТЬ LENGTH = 3
65 JSUB WRREC ЗАПИСЬ EOF
70 75 80 EOF LOL RSUH BYTE RETADR C'EOF' УСТАНОВКА АДРЕСА ВОЗВРАТА ВОЗВРАТ ИЗ ПРОГРАММЫ
85 TK1EE WORD 3
90 ZERO WORD 0
. 95 RETADR RESU 1
300 LENGTH RESU 1 ДЛИНА ЗАПИСИ
105 BUFFER RESB 4096 ДЛИНА БУФЕРА - 4096 БАЙТ
110 *
115 ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР
120 •
125 RDREC LDX ZERO ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА
130 LDA ZERO ОБНУЛЕНИЕ РЕГИСТРА А
135 RL.OOP TD INPUT ПРОВЕРКА УСТРОЙСТВА ВВОДА
140 JEQ RLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ
145 RD INPUT ЧТЕНИЕ СИМВОЛА В РЕГИСТР А .
150 COMP ZERO ПРОВЕРКА НА КОНЕЦ ЗАПИСИ (X/00')
155 JEQ EXIT ВЫХОД ИЗ ЦИКЛА ПО КОНЦУ ЗАПИСИ
140 STCH BOFFERrX ЗАПИСЬ СИМВОЛА В БУФЕР
165 TIX MAXLEN ЦИКЛ ДО ДОСТИЖЕНИЯ
170 JLT KLOOF МАКСИМАЛЬНОЙ ДЛИНЫ
175 EXIT SIX LENGTH ЗАПОМИНАНИЕ ДЛИНЫ ЗАПИСИ
180 RSUB ВОЗВРАТ ИЗ ПОДПРОГРАММЫ
185 INPUT byte: X'Fl' КОД УСТРОЙСТВА,ВВОДА
190 MAXLEN WORD 4096
195 Л
200 M ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ ВУФЕРА
205 M ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА
210 WRREC LDX ZERO
215 WLOOP TD OUTPUT ПРОВЕРКА УСТРОЙСТВА ВЫВОДА
220 JEQ WLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ
225 LDCH BUPP ER,X ЧТЕНИЕ СИМВОЛА ИЗ БУФЕРА
230 WD OUTPUT ВЫВОД СИМВОЛА
235 TIX LENGTH ЦИКЛ, ПОКА НЕ БУДУТ
240 JLT WLOOP ВЫВЕДЕНЫ ВСЕ СИМВОЛЫ
245 KSUB ВОЗВРАТ ИЗ ПОДПРОГРАММЫ
250 OUTPUT BYTE X'05' КОД УСТРОЙСТВА ВЫВОДА
255 END FIRST
Рис. 2.1. Пример программы на языке ассемблера УУМ.
подпрограмм. Главная npoi Г
Программа состоит из трех подпрограмм. 1 лавиая и| •
ма вводит записи с устройства ввода (код устройства
копирует их на устройство вывода (код 05). Она вызывае!
программу RDREC для ввода записи на буфер и подпр»’ г
му WRREC для вывода записи из буфера на устройство i
да. Так как в УУМ имеются только команды RD и WD т
каждая подпрограмма должна передавать данные побайтно
Буфер необходим для согласования скорости обмена устоойст -i
ввода со скоростью выводного устройства (например, магнитно
го диска и устройства печати). В гл. 6 мы увидим, кадля
выполнения этих же функций используются канальные поогпям
мы и макрокоманды операционной системы УУМ/ДС ПоизнТ
ком конца записи служит нулевой код. Признаком конца (Ьай
ла служит запись, имеющая нулевую длину. При обнаружении
конца файла программа выдает признак конца файла EOF на
устройство вывода и заканчивает свою работу возвратом управ
ления вызвавшей программе (возможно, операционной си-
стеме) .
2.1.1. Простой ассемблер для УУМ
На рис. 2.2 показана та же программа, что и на рис. 2.1
но вместе с объектным кодом, сгенерированным для каждого
предложения. В столбце «Адрес» даны шестнадцатеричные ма-
шинные адреса оттранслированной программы. Мы предполага-
ем, что начальный адрес программы равен 1000. Заметим, что
в реальном листинге ассемблера комментарии будут, конечно,
сохранены. В нашем примере они исключены только из-за не-
достатка места.
Для перевода исходной программы в се объектное представ-
действия (не обяза-
ление необходимо выполнить следующие
тельно в указанном порядке):
1. Преобразовать мнемонические коды
валенты на машинном языке — например,
(строка 10).
операций в их экви-
перевести STL в 14
2. Преобразовать символические операнды в эквивалентные
им машинные адреса — например, перевести RETADR в 1033
(строка 10). t
3. Построить машинные команды в соответствующем фор-
мате.
4. Преобразовать константы, заданные в исходной прсирам-
ме, во внутреннее машинное представление (например, в строке
80 оттранслировать EOF в 454F46).
5. Записать объектную программу и выдать листинг.
Все указанные действия, за исключением ВТ0Р^'°’ ^сГ?0°,110й
гут быть выполнены простой построчной 0 Ра ". вает опре-
программы. В то же время трансляция адре
Деленные трудности. Рассмотрим предложение
программы. В то же
Мы
Ле
10 1000 FIRST STL RETADR
и.- можем сразу оттранслировать э™ "ррад0“|™''RETADR.
знаем адрес, который будет присвоен метке
Строка 5 Адрес 1000 Исходное предложение Объектный код
СОРУ START 1000
10 1000 FIRST STL RETADR 141033
15 1003 CLOOP JSUB RDREC
20 25 30 35 40 1006 100? 100С 100F 1012 LDA COMP JEQ JSUB j LENGTH ZERO ENDFIL WRREC 482039 001036 281030 301015 482061
45 1015 ENDFIL LDA CLOOP EOF 3C1003
50 55 60 65 1018 101В 101Е 1021 STA LDA STA JSUB BUFFER THREE length WRREC 00102A 0C1039 00102П 0C1036
70 1024 LDL RETADR 48206t
75 1027 RSUB 08103,$
80 102А EOF BYTE C'EQF' 4C0000
85 102D THREE WORD 3 454F4& 000003 000000
90 1030 ZERO WORD 0
95 1033 RETADR RESW 1
100 1036 LENGTH RESU 1
105 1039- BUFFER RESB 4096
110 M
115 w ПОДПРОГРАММА ВВОДА ЗАПИСИ НА ВУФЕР
120
125 2039 RDREC LDX ZERO 041030
130 203С LDA ZERO 001030
135 203F RLOOP TD ' INPUT E0205B
140 2042 JEQ RLOOP 30203F
145 2045 RD INPUT П8205Г1
150 2048 COMP ZERO 281030
155 204В JEQ EXIT 302057
160 204Е STCH BUFFERrX 549039
165 2051 TIX MAXLEN 2C205E
170 2054 JLT RLOOP 38203F
175 2057 EXIT STX LENGTH 101036
180 205А RSUB 4C0000
185 205D INPUT BYTE X'Fl/ Fl
190 205Е MAXLEN WORD 4096 00100®
195 Jr
200 • ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 210 206t WRREC LDX ZERO 04103®
215 2064 WLOOP ТП OUTPUT E02079 302064
220 2067 JEQ WLOOP
225 206А LDCH BUFFER,X 50903?
230 235 2068 2070 WD TIX OUTPUT LENGTH IIC207? 2C1036 382064 4C0000
240 2073 JLT WLOOP
245 2076 RSUB X/05z
250 2079 OUTPUT byte: KM
255 END FIRST
Рис. 2.2. Объектный КОД для программы на рис. 2.1.
Поэтому большинство ассемблеров выполняет два сМ0Тра
исходной программы. Основной задачей перв адрСсо
является поиск символическисх имен и наз выполняется
Фактическая трансляция, описанная ь >
время второго просмотра.
Ассемблер наряду с трансляцией команд исходной поогоам
мы должен также выполнять и так называемые директивы ас
семблера (иногда их называют псевдокомандами). Эти директи
вы не переводятся непосредственно в машинные команды (хотя
и могут оказывать влияние на объектную программу) а управ
ляют работой самого ассемблера. Примерами таких’ директив
могут служить предложения BYTE и WORD, которые служат
для включения в объектную программу констант, и предложе-
ния RESB и RESW, обеспечивающие резервирование заданного
пространства оперативной памяти. В нашей программе имеют-
ся и другие директивы — START, которая определяет началь-
ный адрес объектной программы, и END, которая отмечает
конец исходной программы.
В заключительной фазе своей работы ассемблер должен за-
писать полученный объектный код на некоторое устройство вы-
вода. Позднее эта объектная программа будет загружена в
оперативную память для исполнения. Для представления объ-
ектной программы мы будем использовать простой формат, в
котором определены три типа записей: запись-заголовок, тело
программы и запись-конец. Запись-заголовок содержит имя
программы, ее начальный адрес и длину. Тело программы со-
держит машинные команды и данные программы с указанием
адресов их загрузки. Запись-конец отмечает конец объектной
программы и определяет адрес, с которого следует начать ис-
полнение программы (точку входа). (Данный адрес задается
операндом предложения END. Если этот операнд не задан, то
в качестве точки входа берется адрес первой исполняемой
команды Д)
Ниже приведены форматы, которые мы будем использовать
для записей объектной программы. Реализация форматов!
мер столбца и т. п.) может быть любой, однако с°дер*
в них информация должна в той или ином форме 1
вать в объектной программе. ______
Запись-заголовок:
Столбец 1
Столбцы 2 — 7
Столбцы 8 — 13
Столбцы 14—19
Н
Имя программы
Начальный адрес
дцатеричный)
Длина программы
теричная)
программы (шестна-
в байтах (шестнадца-
’> Начальный адрес программы не W
••pbo/i выполняемой команды (точкой вход ). Р
Тело программы:
Столбец I
Столбцы 2 — 7
Столбцы 8 — 9
Столбцы 10 — 69
Запись-конец:
Столбец 1
Столбцы 2 — 7
Т
Начальный адрес в данном записи (ше-
стнадцатеричный)
Длина данной записи в байтах (шестна-
дцатеричная)
Объектный код (шестнадцатеричный)
Е
Адрес первой исполняемой команды объ-
ектной программы (шестнадцатеричный)
Для того чтобы избежать путаницы, мы использовали термин
столбец (column), а не байт для ссылки на месторасположения
внутри записей объектной программы. Это отнюдь не означает,
что для хранения объектной программы мы будем использовать
перфокарты (или какое-либо другое специальное представ-
ление) .
НдСОРГ Л001000Л00107А
Тл001000а1Ел141033л482039л00103'6л281030л301015л482061лЗС1003л00102АлОС10 39л001020
ТОО 101 El50С103648206108 10334C0000454F46000003000000
Л ЛЛ Л Л А Л Л Л
ТОО2ОЗ91Е041030001030Е0205D3O2O3FD8205D2810303020575490392С205Е38203F
АЛЛ Л Л А Л Л Л Л Л Л
Т0020571 С1010364C000QF1001000041030E02079302064509039DC20792С1036
ЛЛ Л ЛЛ Л Л Л Л л л
ТОО 2 0 7 30 7 3 8 2 06 4 4 С00000 5
Л Л Л л л
^001000
Рис. 2.3. Объектная программа, соответствующая рис. 2.2.
На рис. 2.3 показан объектный код, соответствующий рас-
смотренной нами программе (рис. 2.2). На этом и последую-
щих рисунках мы будем использовать символ Л для указа-
ния границы полей. Конечно, в реальной объектной программе
этого символа нет. Обратите внимание, что для адресов 1033—
2038 нет соответствующего объектного кода. Эга память просто
резервируется загрузчиком и затем используется программой
во время ее исполнения. (Детальное обсуждение функции за-
грузчика будет приведено в гл. 3.)
Теперь мы можем дать общее описание функций каждого из
двух просмотров нашего простого ассемблера.
Первый просмотр (определение имен):
1. Назначение адресов для всех предложений исходной
программы.
2. Запоминание значений (адресов), присвоенных всем мег-
кам, для последующего их использования на втором
просмотре.
3. Выполнение некоторых директив ассемблера. (К ним от-
носятся директивы, влияющие на адресацию, такие как
BYTE, RESW и т. п.)
Второй просмотр (трансляция команд и генерация объектно-
го кода):
1. Трансляция команд (перевод кодов операций и разреше-
ние адресных ссылок).
2. Генерация данных, заданных директивами BYTE, WORD
И др.
3. Выполнение тех директив ассемблера, которые не были
обработаны на первом просмотре.
4. Запись объектного кода и выдача листинга.
В следующем разделе мы подробнее остановимся на этих
функциях и дадим описание внутренних таблиц ассемблера и
полное описание алгоритмов каждого из просмотров.
2.1.2. Таблицы и алгоритмы ассемблера
Наш простой ассемблер использует две основные внутренние
таблицы: таблицу кодов операций (ОРТАВ) и таблицу симво-
лических имен (SYMTAB). ОРТАВ используется для поиска
мнемонических кодов операций и перевода их в эквивалентные
им представления на машинном языке SYMTAB используется
для хранения значений (адресов), присвоенных символическим
именам.
Еще нам потребуется счетчик адреса (LOCCTR). LOCCTR
это переменная, которая используется для назначения адресов.
Начальное значение LOCCTR определяется операндом предло-
жения START. После обработки очередного предложения
исходной программы длина полученной команды или области
данных прибавляется к LOCCTR. Таким образом, если мы встре-
чаем помеченное предложение исходной программы, то значе-
ние этой метки определяется текущим значением LOCCTR.
Таблица кодов операций должна по крайней мере содержать
Мнемонические коды операций и их машинные эквиваленты.
В более сложных ассемблерах эта таблица, кроме того , содер-
жит информацию о длине и формате каждой команды. Во вре-
мя первого просмотра ОРТАВ используется для поиска и про-
верки корректности задания кодов операций в исходной про-
; грамме. Во время второго просмотра она используется для
перевода мнемонических кодов в их машинное представление.
Фактически в нашем простом ассемблере для УУМ оба эги
Процесса можно совместить в одном просмотре (неважно, в
Первом или во втором). Однако для машин, имеющих форм., ->
L Команд переменной длины (например, УУМ/ДС), нам нсо>
WMo просматривать ОРТАВ и при первом просмотре для
Pass is
begin
прочитать первую входную строку
if OPCODE « 'START' then
begin
запомнить troPERAND) в качестве начального адреса
занести начальный адрес в LOCCTR
записать строку в промежуточный Файл
прочитать следующую входную строку
end
else
занести 0 в LOCCTR
while OPCODE О 'END' da
begin
if это не строка-комментарий then
begin
if есть символ в поле метки then
begin
поиск метки в SYHTAB
if нашли then
занести признак ошибки (второе определение)
else
занести (LABEL,LOCCTR) в SYMTAB
end
Поиск OPCODE в OPTAB
if нашли then
прибавить 3 (длина команды) к LOCCTR
else if OPCODE = 'WORD' then
прибавить 3 к LOCCTR
else if OPCODE = 'RESW' then
прибавить 3 * «OPERAND! к LOCCTR
else if OPCODE « 'RESB' then
прибавить ♦(OPERAND) к LOCCTR
else if OPCODE = 'BYTE' then
begin
определить длину константы в байтах
прибавить длину к LDCCTP
end
else
занести признак ошибки (неверный код операции}
end (if не комментарий)
записать строку в промежуточный файл
прочитать следующую входную строку
end (while)
записать последнюю строку в промежуточный Файл
запомнить (LOCCTR - начальный адрес) в качестве длины программы
end (Pass 1>
Рис. 2.4а. Алгоритм первого просмотра ассемблера.
чтобы определить приращение переменной LOCCTR. При вто-
ром просмотре мы используем ОРТАВ для определения форм а-
а и других специальных характеристик ассемблируемой ко.ман
гтппи-г1НаШСМ слУчае мы решили придерживаться именно
РУ уры, поскольку она типична для большинства асссм°-
леров.
2.1. Основные функции всеемблера
Poss 2 а
47
begin
"r°£rn£ "е'ХЛ'°?ь£ СТ₽“'У Сиэ Л₽ои*^^НОГО ♦*««.)
X» OrLODt. — ЫАК1 then
begin
выдать строку листинга
прочитать следующую входную строку
end
занести запись-заголовок в объектную программу
инициализировать первую запись тела программы
While OPCODE О 'END' do
begin
if это не строка-комментарий then
begin
поиск OPCODE в ОРТАВ
if нашли then
begin
if в поле операнда есть имя then
begin
поиск имени в SYMTA
if нашли then
запомнить значение имени
в качестве адреса операнда
else
begin
запомнить 0 в качестве адреса операнда
занести признак ошибки (имя не определено)
end
end (if есть имя}
else
запомнить 0 в качестве адреса операнда
ассемблирозать команду в объектное представление
end Сif нашли}
else if OPCODE = 'BYTE' или 'WORD' then
преобразовать константу в объектное представление
if объектный код не помещается
в текущей записи тела программы then
begin
занести текущую запись в объектную программу
инициализировать новую запись тела программы
end
занести объектный код в запись тела программы
end Cif не комментарий)
выдать строку листинга
прочитать следующую входную строку
end {while?
занести последнюю запись тела в объектную программу
занести запись-конец в объектную программу
выдать последнюю строку листинга
end {Pass 2>
Рис. 2.46. Алгоритм второго просмотра ассемблера.
Обычно ОРТАВ организуется в виде хеш-таблицы в ко-
торой в качестве ключа используется мнемонический код опе-
рации. (Конечно, ОРТАВ строится заранее — при создании
«перемешанные.
I) в нашей литературе иногда испольаует
Таблицы», — Прим, рчд.
ассемблера, а не во время его работы 1 г.,.,.
очень удобна, поскольку обеспечивает быстрый поиск пр"мТни'
малыюм числе сравнении. В большинстве случаев OPTAR
ставляет собой статическую таблицу, т. е. в процессе раЕ
в ней не создаются новые элементы, а уже определенные Е
исключаются. В этом случае можно построить специают,
хеш-функцию или другую структуру данных, обеспечивают^!
для конкретного набора ключей оптимальное время доступ7
Однако чаще всего используются стандартные хеш-функцин
Подробную информацию о построении хеш-таблиц можно пай'
ти в любом хорошем учебнике по структурам данных наппв
мер в Стендиш [1980] или Кнут [19736]. ’ ри"
Таблица имен (SYMTAB) состоит из имен и значении (аз-
ресов) всех меток исходной программы вместе с признаками
указывающими на ошибку (например, дважды определенное
имя). Эта таблица может также содержать информацию о ти-
пе, длине и других характеристиках помеченной области дан-
ных или команды. Во время первого просмотра все встретив-
шиеся в исходной программе имена вместе с их адресами (они
определяются по LOCCTR) сразу заносятся в SYMTAB. Во
время второго просмотра имена, используемые в качестве опе-
рандов, ищутся в SYMTAB и соответствующие им адреса ис-
пользуются для генерации команд.
Для повышения эффективности поиска и внесения новых
имен SYMTAB обычно организуется также в виде хеш-табли-
цы. Поскольку операция исключения элемента из таблицы при-
меняется крайне редко (скорее никогда), то вопрос об эффск-
тивности ее выполнения не возникает. Интенсивное использо-
вание SYMTAB на протяжении всей работы ассемблера требует
тщательного подбора хеш-функции. Очень часто программис-
ты используют много похожих друг на друга имен, например
имена, начинающиеся или заканчивающиеся одними и теми ж
символами (такие как LOOP1, LOOP2, LOOPA), или имена,
имеющие одинаковую длину (А, X, Y, 2% Важно, чтобы ис-
пользуемая хеш-функция обеспечивала хорошую работу с i <-
кими неслучайными именами. Часто хороший результат доен
гается путем деления входного ключа на простое число, равно
длине таблицы.
Хотя в качестве входной информации на этапе второго пр
смотра можно использовать исходную программу, однако
— после пер
жна быть учтена и информация, полученная ранее
вого просмотра (например, адрес предложения или при
ошибки). Поэтому обычно во время первого просмотра <1’
ется промежуточный файл, который содержит каждое пре
жение исходной программы вместе с его адресом, признак1
ошибки и другой необходимой информацией. Промежуточно^
файл является входным для второго просмотра, Рабочая ко;.-
исходной программы, содержащаяся в промежуточном » -
может быть использована для того, чтобы сохранитX ФаИЛе>
ты некоторых операций, выполненных во время п^вогГппо
смотра (например, операции сканирования поля опепапХ ?
определения имен и способов адресации). Это лает
ность не выполнять их еще раз при втором просмотре Аня™
гично для кодов операции и имен могут быть сохпано.н, ,
затели на таблицы ОРТАВ и SYMTAB, что позволит
жать повторных операций поиска.
На рис. 2.4а и 2.46 представлены алгоритмы соответственно
первого и второго просмотров нашего ассемблера. Эти а пгоритмы
несмотря на то что они описывают простой ассемблер являют-
ся основой для более сложных двухпросмотровых ассемблеров
которые мы рассмотрим позднее. Для простоты мы будем
полагать, что исходная программа записана в фиксированном
формате с полями МЕТКА, ОПЕРАЦИЯ и ОПЕРАНДЫ. Если
какое-либо из этих полей содержит строку символов, пред-
ставляющую число, мы будем обозначать это с помощью пре-
фикса # (например, # [OPERAND]).
На данном этапе очень важно, чтобы вы досконально разо-
брались с алгоритмами, представленными на рис. 2.4а и 2.46.
Вам настоятельно рекомендуется тщательно разобраться в этих
алгоритмах, применив их для ручной трансляции программы
на рис. 2.1 в ее объектное представление на рис. 2.3.
Конечно, для того чтобы сконцентрировать внимание на об-
щей структуре н основных концепциях, мы опустили многие
детали алгоритмов. Вам надлежит самостоятельно обдумать их,
а также определить те функции ассемблера, которые следует
реализовать в виде отдельных процедур пли модулей. (Напри-
мер, операции «поиск в таблице имен» пли «чтение входной
строки» являются хорошими кандидатами на такую реализа-
цию.) Такой внимательный анализ алгоритмов следует делать
всегда, прежде чем приступать к фактической реализации ас-
семблера или какого-либо другого элемента программною о сс-
печения значительного размера.
2.2. Машинно-зависимые характеристики
ассемблера
В этом разделе на примере ассемблера ^ожУюстей' ЭВМ
рассмотрим, как расширение аппарата Архитектура мно«
влияет на структуру и функции ассемо/ I _ Поэтому в
ГИх реальных ЭВМ похожа на стрУ'^Р пкимеННмо Н9 TQ«'lbKQ
Значительной степени наше обсуждс
УУМ/ДС, но и к реальным машинам.
На рис. 2.5 показано, как предыдущая программа (см.
рис. 2.1) может быть записана с использованием дополнителД
ных возможностей системы команд УУМ/ДС. Косвенная адре.
сация в нашем языке ассемблера задается добавлением к опе-
ранду префикса @ (строка 70). Непосредственный операнд обо-
значается префиксом фр (строки 25, 55, 133). Для команд, »
которых есть ссылка на оперативную память, обычно нсполь-
зуется либо адресация относительно счетчика команд, либо
адресация относительно базы. Директива ассемблера BASE
(строка 13) используется в связи со способом адресации относи-
тельно базы. (Подробности и примеры см. в разд. 2.2.1.) В це,
которых командах величина смещения в относительном способе
адресации мо?кет быть очень большой и для ее размещс*ни'|
будет недостаточно поля 3-байтового командного формата. Для
таких команд необходимо использовать 4-баитовый расширь -
ный командный формат. На языке ассемблера этот форма г
задается добавлением к коду операции префикса ф- (см.
строки 15, 35, 65). Ответственность за правильность специф
кации команд расширенного формата возлагается на 1;., ...
граммиста.
Основное отличие новой версии программы от програм i
для УУМ заключается в том, что в ней всюду, где это
можно, используются команды вида регистр — регистр (в
команд вида регистр — память). Например, в строке 150 в-,
предложения COMP ZERO использовано COMPR A, S,
строке 165 вместо TIX MAXLEN использовано T1XR Т. i ?
того, всюду, где это возможно, используются непосредстш .
операнды и косвенная адресация (например, строки 25, " .
Эти изменения внесены для того, чтобы использован,
имущества архитектуры УУМ/ДС с целью увеличения с
сти выполнения программы. Операции вида регистр — р
быстрее, чем соответствующие операции вида регистр — ш
Это связано с тем, что, во-первых, они занимают меньше
в памяти и, во-вторых, что более важно, не требуют допе
тельных ссылок в память для выборки операндов. (Вы
операнда из регистра происходит намного быстрее, чем п
ративной памяти.) Точно так же, когда используется ней
ственный операнд, то при обработке команды он уже npi.*'
ствует как ее составная часть, и, следовательно, нет неоохо :
мости в его выборке откуда-либо еще. Использование косвен!
адресации часто позволяет экономить команду (см. ci
ку 70). Вы. можете заметить, что в то же время некоторые
менения требуют внесения в программу дополнительна
команд. Например, замена команды СОМР на COMPR в С Д'
ке 150 вынудила нас добавить команду CLEAR в строку
ем не менее в, целом скорость выполнения программы во5
тет, так как команда CLEAR выполняется только один 1
Строка Исходное предложение
5 10 12 13 COPY FIRST START STL LDB BASE 0 RETADR ♦LENGTH LENGTH КОПИРОВАНИЕ ФАЙЛА СОХРАНЕНИЕ АДРЕСА ВОЗВРАТА УСТАНОВКА БАЗОВОГО РЕГИСТРА
15 CLOOP *JSU8 RDREC ВВОД ВХОДНОЙ ЗАПИСИ
20 25 LDA COMP LENGTH ♦0 ПРОВЕРКА НА EOF (LENGTH = 0)
30 JEQ ENDFIL ВЫХОД, ЕСЛИ НАШЛИ EOF
35 4-JSUH WRREC ВЫВОД ВЫХОДНОЙ ЗАПИСИ
40 ENDFIL J CLOOP ПИКЛ
45 50 LDA .STA EOF BUFFER ЗАНЕСЕНИЕ МАРКЕРА КОНЦА ФАЙЛА
55 LDA ♦3 УСТАНОВИТЬ LENGTH = 3
60 STA LENGTH
65 4 JSUB WRREC ЗАПИСЬ EOF
70 J ORETADR ВОЗВРАТ ИЗ ПРОГРАММЫ
80 EOF BYTE C'EOF'
95 100 RETADR RESW 1
LENGTH RESU 1 ДЛИНА ЗАПИСИ
105 BUFFER RESB 4096 ДЛИНА БУФЕРА - 4096 БАЙТ
110 « •
115 ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР
120
125 RDREC CLEAR X. ОБНУЛЕНИЕ СЧЕТЧИКА ПИКЛА
130 CLEAR A ОБНУЛЕНИЕ РЕГИСТРА А
132 CLEAR S ОБНУЛЕНИЕ РЕГИСТРА S
133 fLDT ♦4096
135 RLOOP TH INPUT ПРОВЕРКА УСТРОЙСТВА ВВОДА
140 JEQ RLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ
145 RD INPUT ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
150 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ (Х'00
155 JEQ EXIT ВЫХОД ИЗ ЦИКЛА ПО КОНЦУ ЗАПИСИ
160 STCH BUFFER,X ЗАПИСЬ СИМВОЛА В БУФЕР
165 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ
170 JLT RLOOP МАКСИМАЛЬНОЙ ДЛИНЫ
175 EXIT STX LENGTH ЗАПОМИНАНИЕ ДЛИНЫ ЗАПИСИ
180 RSUB ВОЗВРАТ ИЗ ПОДПРОГРАММЫ
185 INPUT BYTE X'Fi.' КОД УСТРОЙСТВА ВВОДА
195 M ЗАПИСИ ИЗ БУФЕРА
200 w • ПОДПРОГРАММА ВЫВОДА
205 210 WRREC CLEAR X ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА
212 215 220 225 230 235 240 WLOOP LDT TD JEQ LDCH WD TIXR JLT LENGTH OUTPUT ULOOP BUFFER,X OUTPUT T WLOOP ПРОВЕРКА УСТРОЙСТВА ВЫВОДА ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ ЧТЕНИЕ СИМВОЛА ИЗ БУФЕРА ВЫВОД СИМВОЛА ЦИКЛ, ПОКА НЕ bWT-., ВЫВЕДЕНЫ ВСЕ СИМВОЛЫ ВОЗВРАТ ИЗ ПОДПРОГРАММЫ
245 250 OUTPUT RSUB BYTE X'05' КОД УСТРОЙСТВА ВЫВОДА
255 END FIRST
для каждой читаемой записи, а команда COMPR Гбплпо г
рая, чем СОМР) выполняется для каждого байга. быст-
В разд. 2.2.1 рассматривается процесс трансляции пппт.
мы для УУМ/ДС. При этом основное внимание обращено на
те отличия ассемблера УУМ/ДС, которые продиктованы новы
мн способами адресации. (Вам следует взглянуть на формат
Л сп°собь1 вычисления целевого адреса, описанные в
разд. 1.3.2.) Эти отличия являются прямым следствием расти
рения аппаратных возможностей.
vvM/nPr34' 222 обсУждаются отличия версии ассемблера
УУМ/ДС, имеющие косвенную связь с новыми аппаратными
возможностями Например, расширенный объем оперативной
памяти УУМ/ДС позволяет предположить, что мы будем иметь
достаточно места для одновременной загрузки и исполнения не-
скольких программ. Такое разделение машины между несколь-
кими программами называется мультипрограммным режимом
обработки. Этот режим позволяет более эффективно использо-
вать аппаратуру ЭВМ. (Мы вернемся к этому вопросу в связи
с операционными системами в гл. 6.) Однако для того, чтобы
полностью использовать преимущества мультипрограммного ре-
жима, мы должны иметь возможность загружать программу в
любое свободное место оперативной памяти (а не в фиксиро-
ванное место, определенное во время трансляции). При этом
возникает необходимость перемещения программ в оперативной
памяти. В разд. 2.2.2 мы обсудим эту проблему в ее связи с
ассемблером.
2.2.1. Форматы команд и способы адресации
В этом разделе мы рассмотрим трансляцию предложении
исходной программы УУМ/ДС (рис. 2.5) в соответствующее им
объектное представление (рис. 2.6), обращая особое внимание
на обработку ассемблером различных командных форматов и
способов адресации. Заметим, что предложение START задав।
теперь 0 в качестве начального адреса программы. Как оуди
сказано в следующем разделе, это является признаком переме-
щаемой программы. Однако процедура трансляции ком<пи
остается при этом такой же, как если бы программа деистьи
тельно загружалась с адреса 0. . . ri г
Трансляция команд вида регистр — регистр, таких как - •
AR (строка 125) или COMPR (строка 150), не представ,
никаких новых проблем. Ассемблер должен просто Г1Рссю^пе.
вать мнемонические коды операций в их машинное продет —
ние (используя ОРТАВ) и заменить мнемонические
гистров на их числовые эквиваленты. Так же как и для е.
других видов, это делается во время второго просмотра-
образование имен регистров в их числовые значения мож*.
Строка 5 Адрес 0000 Исходное предложение Объектный код’
COPY START 0
10 0000 FIRST STL RETADR
12 0003 LDB ♦LENGTH 1/Z02D
13 BASE LENGTH OT4VZU
15 0006 CLOOP +JSUB RDREC ATI
20 000А LDA LENGTH nolv IvjC) 032026
25 000D COMP ♦0 W «и W
30 0010 JEQ ENDFIL 332007
35 0013 4-JSUB URREC 4B10105O
40 0017 J CLOOP 3F2FEC
45 001А ENDFIL LDA EOF 032010
50 001П STA BUFFER 0F2016
55 0020 LDA ♦3 010003
60 0023 STA LENGTH 0F200D
65 0026 4-JSUB URREC 4B10105B
70 002А J 0RETADR 3E2003
80 002D EOF BYTE C'EOF' 454F46
95 0030 RETADR RESU 1
100 0033 LENGTH RESU 1
105 0036 BUFFER RESB 4096
110
115 « ПОДПРОГРАММА ВВОДА ЗАПИСИ НА ВУФЕР
120
125 1036 RDREC CLEAR X B410
130 1038 CLEAR A B400
132 103А CLEAR S B440
133 103С 4-LDT *4096 75101000
135 1040 RLOOP ID INPUT E32019
140 1043 JEQ RLOOP 332FFA
145 1046 RD INPUT DB2013
150 1049 COMPR A,S A004
155 104В JEQ EXIT 332008
160 104Е STCH BUFFER,X 57C003
165 1051 TIXR T JB850
170 1053 JLT RLOOP 3B2FEA
175 1056 EXIT STX LENGTH 134000
180 1059 RSUB 4F0000
185 105С INPUT BYTE X'F1Z Fl
195 «
200 N ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 1»
210 105D WRREC CLEAR X B410
212 105F LOT LENGTH 774000
215 1062 WLOOP ТВ OUTPUT £32011
220 1065 JEQ WLOOP 332FFA
225 1068 LDCH BUFFER,X 53C003
230 106В WD OUTPUT PF2008
235 106Е TIXR T B850
240 1070 JLT WLOOP 3B2FEF
245 1073 RSUB » 4F000A
250 1076 OUTPUT BYTE X'05'
255 END FIRST
латься с помощью отдельной таблицы. Однако г
удобно использовать для этих цепей тяГпт,,, аст° бывает
» SYMTAB заранее заносятся “мена perSoe (а’ X ЛЯ ЭТ0™
и их значения (0, 1 и т. д.). В * и т- Д-)
Для трансляции большинства команд вида память по
используется относительный способ адресации (либГ РегистР
тельно счетчика команд, либо относительно' базы В лТбом
е2У11ае ассемблер должен вычислить смещение, которое являет
ся составной частью объектной команды. Оно вычисляется так
чтобы после его сложения с регистром счетчика команд (рА
или базовым регистром (В) получить требуемый целевой адрес
Конечно, величина полученного смещения должна быть нё
слишком большой, чтобы поместиться в 12-разрядиом none
команды. Это означает, что величина смещения должна нахо-
диться в диапазоне от 0 до 4095 (для адресации относительно
базы) или в диапазоне от —2048 до +2047 (для адресации от-
носительно счетчика команд).
нахо-
Если не подходит ни один из относительных способов адре-
сации (из-за того что величина смещения слишком велика),
следует использовать расширенный 4-байтовый командный фор-
мат (формат 4). Этот формат имеет 20-разрядное адресное
поле, позволяющее хранить полный адрес. В этом случае пи-
какого смещения не
15 0006 CLOOP
адрес команды равен
ся в команде вместе
ванне расширенного
вычисляется. Например, в команде
+ JSUB RDREC 4В101036
1036. Это полный адрес, который хранит-
с признаком, указывающим на использо-
командного формата (разряд е устапов-
лен в 1).
Отметим, что программист должен с помощью префикса +
сам указать команды, в которых используется расширенный
командный формат (см. строку 15). Если нельзя применить пи
один из способов относительной адресации и нет указания оо
использовании расширенного формата, то правильная тран-
сляция команды невозможна. В этом случае ассемблер должен
выдать сообщение об ошибке.
Рассмотрим теперь детально, как вычисляется смещение д.ь
относительных способов адресации. По существу, ассемблер
должен в обратном порядке выполнить те операции, когорью
выполняются при вычислении целевого адреса. Вам сл(- В
вспомнить, как это делается, посмотрев еще раз Раздя ‘
Типичным примером команды, в которой используется I
ция относительно счетчика команд, является команда
10 0000 FIRST STL RETADR 17202D
Во время выполнения команд в УУМ/ДС (как и в
аве ЭВМ) счетчик команд продвигается вперед после вь и
очередной команды (но до ее выполнения). Таким образом
время выполнения команды STL регистр PC будет содержав
адрес следующей команды (в данном случае 0003) Из ли™,
Га МпЬл7паК^е ВИДГ’ ЧТ° Метка RETADR (строка 95) имеет ад-
рес 0030. (Ассемблер, естественно может получить эту инфор-
мацию из SYMTAB.) Необходимое нам смещение вычисляется
как 30 — 3 = 2D. Во время выполнения этой команды ее целе
вой адрес будет вычисляться как (PC) -J- disp, что и дасг нуж
НЫЙ нам результат (0030). Обратите внимание, что разряд р
установлен в 1, что является признаком адресации относитеть-
но счетчика команд. Таким образом, два последних байта ма-
шинной команды содержат код 202. Тот факт, что в данной
команде не используется ни косвенная адресация, ни непосред-
ственное задание операнда, указывается установкой 1 в раз-
ряды п и i. Поэтому первый байт машинной команды содержит
код 17, а не 14 (см. описание значений разрядов-признаков на
рис. 1.1 в разд. 1.3.2).
Другим примером адресации относительно счетчика
может служить предложение
40 0017 J CLOOP 3F2FEC
Здесь адрес операнда равен 0006. Во время выполнения
ды регистр PC будет иметь значение 0001 А. Величина
команд
коман-
смеще-
ния вычисляется как 6— 1А = —14. Так как это отрицательное
число, то оно будет представлено в дополнительном коде. В ма-
шинной команде для поля смещения отводится 12 разрядов.
Поэтому смещение будет записано как FEC.
Аналогичным образом вычисляется смещение для адресации
относительно базового регистра. Основное отличие заключается
в том, что ассемблеру известно значение счетчика команд на
момент выполнения программы, в то время как значение базо-
вого регистра определяется программистом. Поэтому програм-
мист должен сообщить ассемблеру значение базового регистра
на момент выполнения программы. В нашем примере это дела-
ется с помощью директивы ассемблера BASE. Данное предло-
жение (строка 13) сообщает ассемблеру, что базовый регистр
будет содержать адрес метки LENGTH. Предшествующая
команда LDB ^LENGTH загружает это значение в регистр
во время работы программы. До тех пор, пока ассемолер не
встретит другую команду BASE, он будет полагать, что 31
ние базового регистра не меняется. Возможно, что в п0 У
Ших фрагментах программы будет желательно использов I
гистр В для других целей (например, для временного >р
некоторого значения). В этом случае программист' .rg)
пользовать другую директиву ассемблера (например,_ w
ДЛЯ того, чтобы сообщить ему, что содержимое базового реги
стра теперь нельзя использовать для базирования.
Важно уяснить, что BASE и NOBASE это директивы асссмб
лера, которые не переводятся в выполняемые машинные ком н
ды. Для загрузки базового регистра требуемым значением ппп
граммнст должен предусмотреть в программе соответствующие
команды. Если этого не сделать, то целевой адрес будет вычи-
сляться неверно. 1ипичным примером команды, в которой не.
пользуется адресация относительно базы, является команда
160 104Е STCH BUFFER,X 57С003
В соответствии с предложением BASE регистр В будет содер-
жать во время исполнения программы значение 0030 (a ine<-
LENGTH). Адрес метки BUFFER равен 0036. Таким образом
смещение определяется как 36 — 33 = 3. Заметим, что в машин-
ном представлении команды оба разряда х и b установлены в
1, что является признаком адресации относительно базы с ин-
дексированием. Другим примером может служить команда
STX LENGTH (строка 175). Здесь смещение равно 0.
Отметим различия в трансляции предложений в строках 20
и 175. В строке 20 для предложения LDA LENGTH использо-
вана адресация относительно счетчика команд. В строке 175
для STX LENGTH использована адресация относительно базы.
(Если вы вычислите для этой команды смещение относительно
счетчика команд, то убедитесь, что его значение слишком вели-
ко для 12-разрядного поля.) Для предложения в строке 20
можно использовать оба способа адресации. Однако наш ас-
семблер вначале делает попытку использовать адресацию отно-
сительно счетчика команд. Выбор приоритета того или иного
способа адресации достаточно произволен и устанавливается
разработчиком ассемблера.
Трансляция команд, в которых используются непосредствен-
ные операнды, проще, поскольку в них не нужна организация
ссылок на оперативную память. Все, что требуется, это преоб-
разовать операнд во внутреннее представление и занести его в
команду. Типичным примером команды, в которой используется
непосредственный операнд, является команда
55 0020 LDA #3 010003
Операнд 003 хранится непосредственно в команде. Разря i '
установлен в 1, что является признаком непосредственно! о
ранда. Другим примером может служить команда
133 103С + LDT #4096 75101000
В данном случае операнд (4096) слишком велик для 12-разря .
кого поля и поэтому используется расширенный командой
формат. (Если бы операнд был велик и для 20-разрядио »
поля, то мы не могли бы задать его непосредственно
команде.)
Другой способ использовали
показан в команде
я непосредственного операнда
12 0003 LDB # LENGTH 69202D
!3рмДтнРпЛ0ЖеНИ" непосРеДственнь1Й операнд задан щченел!
LENGTH. Поскольку его значением является адрес то «
зультате выполнения этой команды в регистр В будет загоуж
адрес, назначенный переменной LENGTH. Заметим что в тан
ном случае используется комбинация адресации относительно
счетчика команд с непосредственным заданием операнда Хотя
на первый взгляд такая адресация может выглядеть не совсем
обычной, тем не менее она не противоречит предыдущим рас-
суждениям. Дело в том, что в общем случае всегда вначале
вычисляется целевой адрес, и если в команде установлен при-
знак непосредственного операнда, то этот адрес (а не содержи-
мое по этому адресу) будет использован в качестве операнда.
(В предложении LDA в строке 55 разряды х, b и р установле-
ны в 0. Таким образом-, целевой адрес просто совпадает со
смещением 003.)
Ассемблирование команд, использующих косвенную адреса-
цию, фактически не представляет ничего нового. Для того что-
бы получить требуемый целевой адрес, вначале обычным обра-
зом вычисляется смещение. Затем в разряд п генерируемой
команды устанавливается признак косвенной адресации. При-
мером использования адресации относительно счетчика команд
в комбинации с косвенной адресацией является предложение
в строке 70.
2.2.2. Перемещение программ
Как было отмечено ранее, очень часто желательно иметь
возможность одновременно выполнять несколько программ, раз-
деляющих между собой оперативную память и другие ресурсы
машины. Если бы нам заранее было точно известно, какие про-
граммы будут выполняться одновременно, то мы могли бы во
время ассемблирования назначить каждой программе подходя-
щие адреса таким образом, чтобы не было ни взаимного пере-
крытия программ, ни потери места в оперативной памяти. Од-
нако чаще всего столь точное планирование выполнения про-
грамм не пригодно с практической точки зрения. (Обычно
мы не знаем абсолютно точно, когда задания начнут выпол-
няться, сколько времени займет их выполнение и т. п.). Поэто-
му хотелось бы иметь возможность загружать программу на
любое место в оперативной памяти, где для нее имеется дос •
точно пространства. В этом случае фактический начал >
рес программы не известен до момента загрузки
Программа, которую мы рассмотрели в пазл 9 I
ляет собой пример абсолютной программыР (или абсолюпю?п
ассемблирования). Для того чтобы она правильно выполХ^
ее необходимо загрузить с адреса 1000 (т. е. с адресаказна
ченного при ассемблировании). Чтобы убедиться в этом пас'
смотрим команду «ном, рас-
55 101В LDA THREE 00102D
из программы, представленной на рис. 2.2. В объектной про-
грамме (рис. 2.3) этому предложению соответствует команда
00102D, которая обеспечивает загрузку содержимого оператив-
ной памяти по адресу 102D в регистр А. Предположим что мы
попытались загрузить и выполнить эту программу с ачреса
2000 (вместо 1000). В этом случае адрес 102D не будет со-
держать ожидаемого значения. Скорее всего данный адрес бу-
дет принадлежать какой-либо другой пользовательской про-
грамме.
Очевидно, для того чтобы программа могла правильно рабо-
тать, начиная с адреса 2000, мы должны сделать определенные
изменения в адресной части данной команды. С другой сторо-
ны, некоторые фрагменты программы (например, константа 3,
сгенерированная в строке 85) должны остаться неизменными
вне зависимости от начального адреса загрузки. Если рассмат-
ривать объектный код отдельно, то в общем случае невозмож-
но определить, какие значения представляют адреса, зависящие
от месторасположения программы, а
объекты.
какие — неизменяемые
Поскольку ассемблеру не известен фактический адрес нача-
ла загрузки, он не может выполнить необходимую настройку
адресов, используемых программой. Однако ассемблер может
указать загрузчику те части объектной программы, которые
нуждаются в настройке при загрузке. Объектная программа,
содержащая информацию, необходимую для выполнения подоб-
ной модификации, называется перемещаемой программой.
Для того чтобы детально обсудить возникающие здесь проб-
лемы, рассмотрим программу на рис. 2.5 и 2.6. В предыдущем
разделе мы ассемблировали данную программу с нулевым на-
чальным адресом. На рис. 2.7а показана ее загрузка с адре-
са 0. Команда JSUB (строка 15) загружается, начиная с ад-
реса 0006. Ее адресное поле содержит значение 01036, когор<«.
является адресом команды с меткой RDREC. (Это, конечно, те
же самые адреса, которые были назначены ассемблером.)
Предположим теперь, что мы хотим загрузить эту л<е про-
грамму с адреса 5000, как показано на рис. 2.76. 1 спорь
команда с меткой RDREC имеет адрес 6036. Таким образо -
адресная часть команды JSUB должна быть модифицирован-
так, как показано на рисунке. Аналогично, если бы мы затру1
ли программу с адреса 7420 (рис. 2.7в), то потребовалось бы
приведение команды JSUB к виду 4В108456, чтобы ее адрес-
ная часть соответствовала новому значению адреса RDREC.
Обратите внимание, что независимо от того, куда загружа-
ется программа, разница между адресом RDREC и началом
программы составляет 1036 байт. Это означает, что мы можем
а 6 в
Рис. 2.7. Примеры перемещения программ.
решить проблему перемещения программы следующим обра-
Кип К°гда ассемблер генерирует объектный код команды
JoUB, мы полагаем, что он заносит адрес метки RDREC отно-
сительно начала программы. (Вот почему мы установили вна-
чале счетчик адреса равным 0.)
2. Ассемблер, кроме того, вырабатывает команду для за-
грузчика, которая предписывает ему прибавить к содержимому
адресного поля команды JSUB начальный адрес программы.
Естественно, что команда загрузчика должна быть составной
частью объектной программы. Это можно сделать с помощью
Дополнительного типа записи объектного формата записи-мо-
дификатора. Эта запись имеет следующий формат;
Запись-модификатор:
Столбец 1 М.
Столбцы 2 — 7 Начальный адрес модифицируемого адрес-
ного поля относительно начала программы
(шестнадцатеричный).
Столбцы 8 — 9 Длина модифицируемого адресного поля в
полубайтах (шестнадцатеричная).
Длина хранится в полубайтах (а не в байтах), так как моди-
фицируемое адресное поле не обязательно содержит целое чис-
ло байтов. (Например, адресное поле в рассмотренной выше
команде JSUB занимает 20 разрядов, что составляет 5 полу-
байтов.) Месторасположение модифицируемого адресного поля
задается адресом байта, в котором содержатся старшие раз-
ряды адресного поля. Если модифицируемое адресное поле за-
нимает нечетное количество полубайтов, то предполагается, что
оно начинается с середины байта, адрес которого задай в
столбцах 2—7.
Эти соглашения, естественно, тесно связаны с архитектурой
УУМ/ДС. Для других типов машин представление длины ад-
ресного поля в полубайтах может оказаться неудобным (см.
упр. 2.2.7).
Для команды JSUB, которую мы используем в качестве
примера, запись-модификатор должна иметь вид
М00000705
Она указывает на то, что начальный адрес программы необходи-
мо добавить к полю, которое начинается с адреса 00007 (отно-
сительно начала программы), и что длина адресного поля рав-
на 5 полубайтам. Таким образом, в ассемблированной команде
4В101036 первые 12 разрядов (код 4В1) останутся неизменны-
ми. Адрес начала загрузки программы будет добавлен к по-
следним 20 разрядам (01036) для того, чтобы получить пра-
вильный адрес операнда. (Вам следует самостоятельно убедить-
ся в том, что это даст результат, показанный на рис. 2.7.)
Точно такие же действия необходимо выполнить для пере-
мещения команд, заданных в строках 35 и 65 (рис. 2.6).
Остальные команды не требуют модификации при загрузке.
В одних случаях потому, что операнды команд расположены не
в оперативной памяти (например, CLEAR S или LDA
В других потому, что для задания операнда использована oi*
носительная адресация. Например, команда в строке Ю (SH-
RETADR) ассемблируется с помощью адресации относительно
счетчика команд со смещением 02D. Неважно, с какого адреса
будет фактически загружена программа. В любом случае сло-
во, помеченное меткой RETADR, будет смещено на заданную
величину (2D) относительно команды STL, Поэтому данную
команду модифицировать не нужно, так как во время ее ви
полпенни счетчик команд будет содержать реальный адрес сле-
дующей команды и, таким образом, процесс вычисления рече-
вого адреса обеспечит получение правильного реального атрс'
са, соответствующего RETADR. '
Точно так же расстояние между LENGTH и BUFFER всегда
будет равно трем байтам. Таким образом, после смещения
команды в строке 160, использующей адресацию относительно
базы, не будет требовать модификации при перемещении про-
граммы. (Содержимое базового регистра будет, конечно, зави-
сеть от месторасположения программы однако его значение
устанавливается автоматически при выполнении команды LDB
^LENGTH, в которой используется адресация относительно
счетчика команд.)
H^COPY д000000д00107 7
1^000000^1 0д1 7202 Од69 202 Вд4 В10 10 36д03 2О26д2 90000дЗ 3 200 7д4 В10 1 0 5D3 F 2 FECO 32010
Тл00001 0д1 Зд0Г201 6д01 000 3ДОР2 000Д4 В1 0 105D3E2 003д4 54 F4 6
Тд0010 36д10дВ4 1 0дВ4 00^В440д7 5 10 1000дЕ 320 1 9д3 32 FFiyDB2 01 ЗдА004д332008д5 7 С00 З.В8 50
Тд001053д1ОлЗВ2РЕАд134 000д4Г0000лГ1лВ410л7 74000лЕ3 201 1л3 32РГАл5 3С00 3дОГ2 0О8В8 50
ТО 010 7 00 73 В 2 F Е F4 F 0 0 0 00 5
л л л л • л
Мл000007л05
^00001^05
>1^00002 7^05
Ед000000
Рис. 2.8. Объектная программа, соответствующая рис. 2.6.
Теперь нам абсолютно ясно, что модификация во время за-
грузки требуется только в командах, использующих прямую
(как альтернатива относительной) адресацию. Для программ
УУМ/ДС прямая адресация используется только в расширен-
ном (4-байтовом) командном формате. Это существенное пре-
имущество относительной адресации. Если бы мы попытались
переместить программу, приведенную на рис. 2.1, то увидели
бы, что почти все команды требуют модификации.
На рис. 2.8 показано объектное представление, соответству-
ющее исходной программе на рис. 2.5. Обратите внимание, что
записи тела программы остались такими же, как если бы они
были подготовлены абсолютным ассемблером (с нулевым на-
чальным адресом). Однако теперь адреса загрузки рассматри-
ваются не как абсолютные, а как относительные величины.
(То же самое, конечно, справедливо для адресов в записях-мо
лификаторах и записи-конце.) Для каждого адресного • >
требующего настройки при перемещении пР°гРам!^“’ ” я
своя запись-модификатор (в пашем случае их 3 ’’
команд -|-JSUB). Вам следует самостоятельно провер
дую запись-модификатор и убедиться, что вы поняли как она
формируется. В гл. 3 мы детально рассмотрим, как загрузчик
осуществляет требуемую модификацию программ. Сейчас важ-
но, чтобы вы хорошо уяснили изложенные здесь концепции так
как они послужат основой для материала, обсуждаемого в’спе
дующем разделе.
2.3. Машинно-независимые характеристики
ассемблера
В этом разделе мы обсудим некоторые общие характе-
ристики ассемблера, не имеющие тесной связи со структурой
машины. Конечно, более совершенные машины обычно имеют
более сложное программное обеспечение, и поэтому средства
ассемблера, которые мы здесь рассмотрим, вероятнее встретить
на больших и сложных машинах. Однако наличие или отсут-
ствие этих средств определяет скорее такие факторы, как удоб-
ство программирования или операционное окружение, нежели
структура конкретной машины.
В разд. 2.3.1 мы обсудим таблицы и алгоритмы, необходи-
мые для реализации литералов. В разд. 2.3.2 будут рассмотре-
ны две директивы ассемблера (EQU и ORG), основной функ-
цией которых является определение имен. В разд. 2.3.3 коротко
рассматриваются выражения в языке ассемблера. Обсуж-
даются различные типы таких выражений, их вычисление и
использование.
В разд. 2.3.4 и 2.3.5 мы познакомимся с такими важными
понятиями, как программный блок и управляющая секция. Мы
обсудим доводы в пользу включения этих средств в ассемблер
и проиллюстрируем их использование с помощью примеров. Мы
также познакомимся с набором директив ассемблера, которые
служат для поддержания этих средств, и обсудим пути их ре-
ализации.
2.3. Г. Литералы
Очень часто бывает удобно иметь возможность записывать
значения константы, используемой в качестве операнда, непо-
средственно в команде, где она используется. Это позволяет от-
казаться от использования отдельного предложения для опре-
деления константы и соответствующей ей метки. Такой опе-
ранд называется литеральным (literal), поскольку значение кон-
станты задается в виде строки символов. На рис. 2.9 при-
веден пример использования литералов. Объектный код, сгене-
рированный для предложений этой программы, показан на
рис. 2.10. (Эта программа является модификацией программы.
М Маи1И,„„.„езаписнмы1 х.рактериет„>„ ,
63
Строка Исходное предложение
5 10 13 14 15 20 25 30 35 40 45 50 55 60 65 70 93 95 100 105 106 107 110 115 120 125 130 132 133 135 140 145 150 155 160 165 170 175 180 185 195 200 205 210 212 215 220 225 230 235 240 245 255 COPY FIRST CLOOP ENDFIL RETADR LENGTH BUFFER BUFEND MAXLEN A « RDREC RLOOP EXIT INPUT • WRREC WLOOP STLRT ГСТАПО КОПИРОВАНИЕ ФАЙЛА L№ «LENGTH XCTAHOBKA^SSofinr E'°3№ATA BASE LENGTH СНОВКА БАЗОВОГО РЕГИСТРА +LDA* LENGTH S -ВХ°ДН0Й ЗАПИСИ COMP «0 ВЕРКА HA EOF (LENGTH = 0) +JSUB Sr" ВЫХ0Дг ЕСЛИ НАШ™ EOF J CLOOP ЕД ВЬ1Х0ДН0* ЗА"ИСИ sta "buffer занесение маркера конца файла sta Length УСТАН0ВИТЬ LENGTH = 3 +JSUB WRREC ЗАПИСЬ EOF LTOR6 eRETADR ВОЗВРАТ ИЗ ПРОГРАММЫ RESW 1 RESW 1 ДЛИНА ЗАПИСИ RESB 4096 ДЛИНА БУФЕРА - 4096 БАЙТ E0U * EOU BUFEND-BUFFER МАКСИМАЛЬНАЯ ДЛИНА ЗАПИСИ ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР CLEAR X ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА CLEAR А ОБНУЛЕНИЕ РЕГИСТРА А CLEAR S ОБНУЛЕНИЕ РЕГИСТРА S +LDT «MAXLEN TD INPUT ПРОВЕРКА УСТРОЙСТВА ВВОДА JEQ RLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ RD INPUT ЧТЕНИЕ СИМВОЛА В РЕГИСТР А COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ (X'00z) JEQ EXIT ВЫХОД ИЗ ЦИКЛА ПО КОНЦУ ЗАПИСИ STCH BUFFER, X ЗАПИСЬ СИМВОЛА В БУФЕР TIXR Т ЦИКЛ ДО ДОСТИЖЕНИЯ JLT RLOOP МАКСИМАЛЬНОЙ ДЛИНЫ STX LENGTH ЗАПОМИНАНИЕ ДЛИНЫ ЗАПИСИ Rchr ВОЗВРАТ ИЗ ПОДПРОГРАММЫ BYTE XfF1f КОД УСТРОЙСТВА ВВОДА ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА CLEAR х ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА LDT LENGTH ПРОВЕРКА УСТРОЙСТВА ВЫВОДА ™ !иК ПОЖЕНИ» ГОТОВНОСТИ Гпги BUFFER X ЧТЕНИЕ СИМВОЛА ИЗ БУФЕТА S Н -Х'05' ВЫВОД СИМЮЛА rvnyr W® "X 0 ЦИКЛ, ПОКА НЕ ВУ^УГ TIXR Т д ВЫВЕДЕНЫ ВСЕ СИМВОЛЫ JLT WLOOP ВОЗВРАТ ИЗ ПОДПРОГРАММЫ. RSUB END FIRST
Рис. 2.9. Программа,
L'-'-.OJtpd,
демонстрирующая
дополнительные
возможности ао
Строк» Адрес Исяодмое предложение Ойгеигнмй код
5 0000 COPY START 0
10 0000 FIRST STL RETADR 17202П
13 0003 LDB ♦LENGTH 69202D
14 BASE LENGTH
15 0006 CLOOP 4 JSUB RDREC 4B101036
20 000А LDA LENGTH 032026
. 000D COMP ♦0 290000
30 0010 JEQ ENDFIL 332007
35 0013 •f JSUB WRREC 4B10105O
40 0017 J CLOOP 3F2FEC
45 001А ENDFIL LDA =C'EOF' 032010
50 001D STA BUFFER 0F2016
55 0020 LDA ♦3 010003
60 0023 STA LENGTH 0F200D
65 0026 +JSUB WRREC 4B10105L
70 002А J 8RETADR 3E2003
93 LTORG
002D м -C'EOF t 454F46
95 0030 RETADR RESW 1
100 0033 LENGTH RESW 1
105 0036 BUFFER RESB 4096
106 1036 BUFEND EQU *
107 1000 MAXLEN EQU BUFEND-BUFFER
110 •
115 • ПОДПРОГРАММА ВВОДА ЗАПИСИ НА ВУФЕР
120 •
125 1036 RDREC CLEAR X B410
130 1038 CLEAR A B400
132 103 А CLEAR S B440
133 103С +LDT ♦MAXLEN 75101000
135 1040 RLOOP TD INPUT E32019
140 1043 JEQ RLOOP 332FFA
145 1046 RD INPUT DB2013
150 1049 COMPR A,S A004
155 104В JEQ EXIT 332008
160 104Е STCH BUFFER,X 57C003
165 1051 TIXR T B850
170 1053 JLT RLOOP 3B2FEA
175 1056 EXIT STX LENGTH 134000
180 1059 RSUB 4F0000
185 105С INPUT BYTE X'Fl' Fl
195
200 ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 w
210 105D WRREC CLEAR X B410
212 105F LDT LENGTH 774000
215 1062 WLOOP TD =X'05Z E32011
220 1065 JEQ WLOOP 332FFA
225 1068 LDCH BUFFERFX 53C003
230 106В WD *=X'05' DF200S
235 106Е TIXR T B850
240 1070 JLT WLOOP 3B2FEF
245 1073 RSUB 4F0000
255 END FIRST
1076 * *=X'05' 05
Рис. 2,10. Объектный код для программы на рис, 2.9
- Маш..,„.с,,„м^рмт|!риствк||
м —------ 65^
представленной на рис. 2.5: лпугир и^с ----
разд. 2.3.) °’ Другие изменения мы Обсуднм „
В нашем языке ассемблот
префикса =, за которым следует кометан^Гз'^4 С ПОМО1Ныо
жениТ’ В ПреАЛ0Жении ВуТЕ. Таким образом.'Г^е°Х
45 001A ENDFIL LDA =C'EOF' 032010
литерал определяет 3-байтовый операнд, значением «nTnh
является строка символов EOF. Аналогично в прХоже.шГ
215 1062 WLOOP TD =Х'О5' Е32011
задается 1-байтовый литерал, имеющий шестнадцатеричное
значение 05. Символьная нотация для задания литералов ?.м-
жет быть различной, однако в большинстве ассемблеров для
того, чтобы упростить идентификацию литералов, используется
определенный символ (у нас =).
Важно уяснить различие между литералом и непосредствен-
ным операндом. В случае непосредственного операнда его зна-
чение транслируется как составная часть машинной команды.
В случае литерала его значение генерируется в виде константы
в оперативной памяти, а ее адрес используется в качестве це-
левого адреса команды. Употребление литерала даст точно та-
кой же результат, как если бы программист явно определил
константу и использовал в качестве операнда ее метку. (Дейст-
вительно, сгенерированный объектный код для строк 45 и 215
на рис. 2.10 идентичен объектному коду для соответствующих
строк программы на рис. 2.6.) Вам следует сравнить объект-
ный код, сгенерированный для строк 45 и 55 (рис. 2.10), для
того, чтобы убедиться, что вы уяснили разницу в обработке ли-
тералов и непосредственных операндов.
Все литеральные операнды, используемые в программе, ооь-
единяются в один или несколько литеральных пулов (htcra s
pools). Обычно литеральный пул помешается в копие програм
мы и распечатывается в ее листинге. В литеральном пуле для
каждого литерала показаны назначенный ему адрес 11 С[
рнрованное значение. Пример такого литеральною Г1>' сд.
веден на рис. 2.10 (он расположен непосредственно> °
ложения END). В данном случае пул состоит то/
кого литерала =Х'05'. - пязмешать лите-
Однако в некоторых случаях 'аумы. Это можно
ральный пул в другом месте объект Р . (строка 93
сделать с помощью директивы предложение LTORG.
на рис. 2.9). Когда ассемблер всдР^ае вРсе литеральные опе-
он создает литеральнып пул, с°ДЧ в программе с М()ме"'а‘
ранды, которые были исподьзо < > lTORG (или с пая
обработки предыдущего пред.
программы). Литеральный пул помещается в объектную про-
грамму в го место, где было встречено предложение LTORG
(см. рис. 2.10). Конечно, литералы, помещенные в литеральный
пул по команде LTORG, не будут повторно помещаться в лите-
ральный пул в конце программы.
Если бы мы не использовали предложение LTORG в строке
93, то литерал =C'EOF' был бы помещен в литеральный пул
в конце программы. В этом случае данный операнд получил бы
адрес 1073 и мы не смогли бы использовать для него адреса-
цию относительно счетчика команд. Конечно, все дело в том,
что мы зарезервировали очень большое пространство для мас-
сива BUFFER. Расположив литеральный пул перед этим мас-
сивом, мы смогли избежать использования расширенного
командного формата для ссылок на литералы. Обычно необхо-
димость в команде, подобной LTORG, возникает тогда, когда
желательно расположить литеральные операнды в непосредст-
венной близости от команд, в которых они используются.
Большинство ассемблеров умеют распознавать повторное ис-
пользование литералов и хранят только один экземпляр каж-
дого из них. Например, литерал =Х'О5' используется в нашей
программе в строках 215 и 230. Однако для его хранения гене-
рируется только одна константа и операнды обеих команд ссы-
лаются на адрес этой константы.
Простейший способ распознать повторное использование
литерала заключается в сравнении определяющих их строк сим-
волов (в нашем случае это строка =Х'О5'). Однако в некото-
рых случаях лучше сравнивать не определения, а сгенерирован-
ные коды. Например, литералы =C,EOF' и =X'454F46' опре-
деляют идентичные значения. Если бы ассемблер умел
распознавать их эквивалентность, то он мог бы не заводить
дублирующую константу. В то же время выигрыш от подобного
способа обработки литералов обычно не столь велик, чтобы
оправдать дополнительные усложнения ассемблера.
Если для распознавания повторного использования литера-
лов используется символьная строка, то следует быть внима-
тельными при обработке литералов, значение которых зависит
от месторасположения в программе. Предположим, что мы раз-
решаем использовать литералы, которые ссылаются на теку-
щее значение счетчика размещений (часто обозначаются с по-
мощью символа *). Такие литералы иногда бывают полезнь
для загрузки базового регистра. Например, предложения
LDB = *
BASE *
расположенные в самом начале программы, обеспечивают за
1рузку в регистр В начального адреса программы. В дальней
2 4 Машннио-псзаписимые характеристики ассемблера G7
шем это значение можно использовать для адресации относи-
тельно базы.
Однако такое обозначение может вызвать трудности распо-
знавания повторно используемых литералов. Если литерал ==*
появился бы в нашей программе в строке 13, то его значение
было бы 0003. Если тот же операнд был бы задан в строке 55,
то он определял бы операнд, имеющий значение 0020. В этом
случае литеральные операнды имеют идентичные имена, но
различные значения. Следовательно, оба эти операнда должны
быть помещены в литеральный пул. Те же самые проблемы
возникают, если литерал ссылается на какой-либо другой объ-
ект, значение которого изменяется между двумя точками про-
граммы.
Теперь мы готовы к тому, чтобы описать, как ассемблер
обрабатывает литеральные операнды. Основной структурой дан-
ных, используемой при обработке литералов, является таблица
литералов LITTAB. Для каждого использованного в программе
литерала эта таблица содержит следующую информацию: имя
литерала, его значение, длину и назначенный ему адрес. Очень
часто LITTAB организуется в виде хеш-таблицы, в которой
в качестве ключа используется имя литерала или ею
значение.
Если во время первого просмотра ассемблер встречает лите-
ральный операнд, то он пытается найти его в LIT ГАВ. Если
литерал уже присутствует в таблице, то никаких дополнит еди-
ных действий не требуется. Если литерала в таблице еще нс г,
то он помещается в LITTAB (значение адреса пока остаемся
неопределенным). Когда во время первого npocMoipa встреча
ется предложение LTORG или конец программы, ассем лер
просматривает таблицу литералов и назначает каждому .
ралу его адрес (за исключением тех литералов, котор . *
са были назначены ранее). После назначения , р •
редкого литерала счетчик размещении продвиг
Л"ТЛВЬРХ° второго^п'росмотра адреса аптер— операнде»
извлекаются из L1ГТАВ и используютс д. )в в литеральном
кого кода. Значения литеральных о I б ной программы
пуле заносятся в соответствующие м «Ыли сгенерированы с
точно так же, как если бы эти звач^орО, Если значение ли-
помощью предложений But программный адрес
теральнего операнда пРедстав'™^,,е1Лений), то ассемблер дол*
(например, значение с’е”илас^“етХук>шук> занись-модифи-
жен сгенерировать для hli
катор в объектном пР®дставдвН1ц1’0 вы поняли, как создав^ввть
Для того чтобы У6“П™ ’ лоз, вам ЛГ"МЙ
используется таблица л 1
описанную нами процедуру к исходной программе на оно о о
Объектный код и литеральные пулы, которые вы получит?
Должны быть такими, как показано па рис. 2.10. У ’
2.3.2. Средства определения имен
До сих пор в рассмотренных нами ассемблерных програм-
мах мы имели дело только с одним способом определения сим-
волических имен пользователя. Эти имена появлялись в каче-
стве меток команд или областей данных. Значением такой мет-
ки является адрес, назначаемый предложению, в котором она
определена. Большинство ассемблеров предоставляет програм-
мисту дополнительные средства для определения имен и зада-
ния их значений. К числу обычно используемых директив ас-
семблера относится директива EQU (от EQUate). В общем виде
это предложение записывается следующим образом;
имя EQU значение
Данное предложение определяет некоторое имя (т. е. вносит
его в SYMTAB) и присваивает ему значение. Значение может
задаваться в виде константы или выражения, в котором могут
использоваться константы и ранее определенные имена. Обра-
зование и использование выражений мы обсудим в следующем
разделе.
Одним из общих применений EQU является введение сим-
волических имен вместо числовых значений, чтобы упростить
чтение программы. Например, в строке 133 программы на
рис. 2.5 для того, чтобы загрузить в регистр Т число 40%, мы
использовали предложение
+ LDT # 4096
Данная величина представляет собой максимальную длину за
писи, которую мы можем прочитать с помощпю подпрограммы
RDREC. Однако смысл этого предложения далеко не очевиден.
Если мы включим в нашу программу предложение
MAXLEN EQU 4096
то сможем записать строку 133 как
+ LDT 4 MAXLEN
. > 4 Л'
Когда ассемблер встретит предложение EQU, он занесет _ '
LEN в таблицу имен (со значением 4096). Во вРем<?уд!тдр
ляции команды LDT ассемблер найдет MAXLEN в о > - cMbift
и использует его значение в качестве операнда. Получи *
при этом объектный код будет таким же, как и в предыД
версии, однако исходная программа легче для понимания.
ме того, если понадобится изменить значение величины ЗЯПя.
щей максимальную длину записи, то проще сделать это
ком предложении EQU, чем искать все вхождения 4096 в кс
ходкой программе. УО в ис'
Другое общее применение EQU заключается в определении
мнемонических имен для регистров. Мы предположили ""о
наш ассемблер распознает стандартные мнемонические имена
регистров А, X, L и т. д. Однако представим себе, что ас
семблер требует использовать для задания регистров их номе
ра (например, в команде RMO). Тогда мы должны были
бы писать RMO 0, 1 вместо RMO А, X. В этом случае програм-
мист мог бы включить в свою программу следующую последо-
вательность предложений:
A EQU 0
X EQU 1
1. EQU 2
В результате обработки этих предложений имена А, X, L, ...
были бы занесены в SYMTAB и имели бы значения 0, 1,
2, ... . После этого команда, подобная RMO А, X, была бы до-
пустима. Ассемблер, обрабатывая такое предложение, должен
был бы просмотреть SYMTAB и при трансляции использовать
для имен А и X соответствующие им значения 0 и 1.
На машине, подобной УУМ, задание для регистров пользо-
вательских имен большого смысла не имеет. Гораздо проще
использовать символические имена, встроенные в ассемблер.
К тому же стандартные имена (base, index и т. п.) отражают
способ использования регистров. Рассмотрим, однако, машину,
имеющую регистры общего назначения (например. System 370).
Обычно для обозначения этих регистров используются номера
вида 0, 1, 2, ... или имена вида RO, RI, R2.В конкрепюи
программе некоторые из них могут быть использованы как аа-
зовые регистры, другие — как индексные, третьи—-как с^мма
торы и т. д. Более того, в различных программах функционалi -
ное распределение регистров может быть различным. ’
случае программист может определить имена’« 1 ограммы
функциональное назначение регистров конкрсп о
с помощью следующих предложений:
BASE EQU 1
COUNT
INDEX
Имеется
EQU
EQU
еще
одна
лера, позволяющая косвенно
2
3
именам. Обычно эта директива называется ORG (от Г»о;г- \
Она имеет следующий вид: v кнлп).
ORG значение
где значение представляет собой константу или выражение в
котором могут быть использованы константы и ранее опредс
ленные имена. Если во время ассемблирования программы
встречается данное предложение, то заданное им значение за-
носится в счетчик размещений (LOCCTR). Поскольку для
определения значений имен используется LOCCTR, то предло-
жение ORG распространяет свое влияние на все последующие
определения меток.
Конечно, ввиду того что счетчик размещений используется
для управления распределением памяти в объектной программе,
его изменение чаще всего приводит к ошибкам ассемблирова-
ния. Однако иногда предложение ORG может быть полезно.
Предположим, что мы хотим определить таблицу, имеющую
следующую структуру:
STAb
100 элементов
В этой таблице SYMBOL представляет собой 6-байтовое поле
для хранения имен; VALUE — 1-словное поле для хранения
значения, присвоенного имени; FLAGS — 2-байтовое поле д.
спецификации типа и другой информации. о
Мы могли бы зарезервировать пространство для этой таолп-
цы с помощью предложения
STAB RESB 1100
Естественно, что мы хотим иметь возможность ссылаться >
элементы таблицы с помощью индексной адресации (помешан
в индексный регистр величину смещения требуемого элемент
относительно начала таблицы). Так как нам нужен доев'- '
отдельным полям элементов, то мы должны определить мет'
SYMBOL, VALUE и FLAGS. С помощью предложений LL
это можно сделать следующим образом;
SYMBOL EQU
VALUE EQU
FLAGS EQU
STAB
STAB + 6
STAB + 9
2.3. Млитнио.независимые характеристики ассемблера
71
Теперь для ссылки на поле VALUE мы можем исполу
предложения вида пс“ользовать
LDA VALUE,X
Однако такой способ определения лишь задает метин
дает наглядного представления о структуре таблицы ’
С помощью предложения ORG мы можем определите те
имена следующим образом:
не
же
STAB RESB 1100
ORG STAB
SYMBOL RESB 6
VALUE RESW 1
FLAGS RESB 2
ORG STAB 4-1100
Первое предложение ORG заносит в счетчик размещений на<
чальный адрес таблицы STAB. В следующем предложении мет-
ке SYMBOL будет присвоено текущее значение LOCCTR (т е
тот же адрес, что и STAB). Затем LOCCTR будет продвинут
и его новое значение (STAB + 6) будет присвоено метке VA-
LUE. Аналогично будет определено значение метки FLAGS.
В результате эти метки получат такие же значения, как и при
определении с помощью EQU, но теперь структура STAB стала
очевидной.
Последнее предложение ORG очень важно. Оно возвращает
в LOCCTR значение, которое было в нем до первого предло-
жения ORG — адрес первого свободного байта, следующего за
таблицей STAB. Это необходимо сделать для того, чтобы в по-
следующих предложениях меткам, которые не являются частью
STAB, были назначены правильные адреса. В некоторых ас-
семблерах предыдущее значение LOCCTR запоминается авто-
матически, и для его восстановления достаточно просто напи-
сать предложение ORG с пустым операндом.
Определения, задаваемые предложениями EQU и ORG, со-
держат ограничения, являющиеся общими для всех Директив
ассемблера, в которых определяются имена. В случае EQL все
метки, используемые в правой части предложения (т. е. все
термы, используемые для определения значения нового имени ’
должны быть уже определены. Таким образом, последо
ность предложений
ALPHA RESW 1
BETA EQU ALPHA
является допустимой, тогда как последовательность
BETA EQU ALPHA
ALPHA RESW 1
недопустима. Причина этого ограничения кроется в самом пп<
пессе распознавания имен. Так, во втором случае мы нс см?
жем присвоить значение метке ВЕТА (так как метка А1 рил
еще не определена), а алгоритм работы нашего двухпросмотгк?
вого ассемблера требует, чтооы все имена были определены
время первого просмотра. ’ °
Сходные ограничения применяются и для предложения ORC-
все имена, используемые для задания нового значения счетч?
ка размещений, должны быть предварительно определены Таг
например, последовательность ‘ ’
ORG ALPHA
ВГГЕ1 RESB 1
BYTE2 RESB 1
BYTE3 RESB 1
ORG
ALPHA RESW 1
не может быть обработана. В данном случае ассемблер нс зна-
ет (во время первого просмотра), какое значение следует уста-
новить в счетчик размещений в ответ на первое предложение
ORG. В результате невозможно во время первого просмотра
вычислить адреса для меток BYTEI, BYTE2, BYTE3.
Может показаться, что данное ограничение возникло вслед-
ствие конкретного распределения функций между первым и
вторым просмотрами нашего ассемблера. На самом деле это
проблема носит более общий характер, и она связана с труд-
ностями, возникающими при разрешении ссылок вперед. Легко
можно убедиться, что последовательность предложений
ALPHA EQU BETA
BETA EQU DELTA
DELTA RESW 1
не может быть обработана с помощью обычного двухпросмот-
рового ассемблера при любом распределении функций между
его первым и вторым просмотрами. В разд. 2.4.3 мы вкратце
познакомимся, как осуществляется обработка подобных после-
довательностей в более сложных ассемблерах.
2.3.3. Выражения
Во всех предложениях языка ассемблера, рассмотрена14
нами ранее, в качестве операндов использовались отделы!'"
термы (константы, метки и т. п.). В большинстве ассемблер1
наряду с одиночными термами разрешается использовать
ражения. Каждое такое выражение вычисляется асссмолср1
во время трансляции, а затем полученное значение используй
в виде адреса или непосредственного операнда.
Обычно допускаются арифметические выражения, kotodho
строятся по стандартным правилам с помощью операций | *
/. Деление чаще всего определяется как целочисленное’.
В выражениях можно использовать константы, метки и специ-
альные термы. Одним из таких общеупотребительных специаль-
ных термов является терм, ссылающийся на текущую величину
счетчика размещений (часто обозначается как»)- Значением
этого терма является адрес, который будет присвоен очеред-
ной команде или области данных. Так, на рис. 2.9 предложение
106 BUFEND EQU *
устанавливает в качестве значения BUFEND адрес байта, рас-
положенного непосредственно после поля, отведенного под бу-
фер.
В разд. 2.2 мы обсуждали проблемы, связанные с переме-
щением программ. Мы видели, что в объектной программе име-
ются адреса двух типов: относительные (их значения могут
быть вычислены суммированием начального адреса програм-
мы с некоторым постоянным смещением) и абсолютные (нс за-
висящие от начального адреса программы). Аналогично могут
быть относительными или абсолютными термы и выражения.
Константа — абсолютный терм. Метки команд и областей дан-
ных, а также ссылка на текущее значение счетчика размеще-
ний— относительные термы. Имена, определенные в предложе-
ниях EQU (или других подобных директивах ассемблера), могут
быть как абсолютными, так и относительными в зависимости
от выражений, определяющих их значения.
Выражения классифицируются как абсолютные или отно-
сительные в зависимости от того, к какому типу относится его
значение. Естественно, что выражение, состоящее только нз аб-
солютных термов, является абсолютным выражением. Однако
абсолютное выражение может содержать и относительные тер-
мы. Для этого необходимо, чтобы относительные термы обра-
зовывали пары, причем в каждую пару должен входить как
терм со знаком плюс, так и терм со знаком минус. Совершен-
но необязательно, чтобы парные термы располагались друг за
Другом. Единственное требование — иметь возможность так пре-
образовать выражение, чтобы все термы могли быть сгруппи-
рованы в пары, в каждую из которых входит как положитель-
ный, так и отрицательный терм. Относительные термы нс могут
быть использованы в операциях умножения и деления.
Относительное выражение — это выражение, в котором все
относительные термы, кроме одного, могут быть объединены в
нары, как это было описано выше, причем терм, не вошедший
ни в одну из пар, должен быть положительным. Как и в пер-
ком случае, относительные термы нельзя использовать в ош^
рапиях умножения и деления. Выражения, которые ш
—.
«гловиям абсолютного выражения, ни уСЛо.
удовлетворяют ни умов отмечаются ассемблером Kas
пням относительного вь,
ошибочные. правила могут показаться прощ.
Хотя приведенные вь римеют глубокий смысл. К числч
вольными, они на самом де нЫМ определениям, относят
выражений, УД°в^^я°Р3Ян^ения которых не теряют смысла при
только те выражения зна ОСнтелы1ЫЙ терм или выражен^,
перемещении программ^ значение, которое может i>w.
представляет собой "еД0Тг°?е S - начальный адрес программ
записано в виде ( ’ относительно начального адреса.
я г — величина смещения о задает некоторую точку иг.<
этому Обычно оти°“”л““осителы1ые термы комбинируются „
программы. Когда относ. термы с противоположи;-
пРары.Ркаждая из начальный адрес
ми знаками, ^“"исключаюТя В результате получается а...,-
^^^ВГнапример, программу на рис. 2.9. В
ВИИ107 MAXLEN EQU BUFEND - BUFFER
обе метки BUFEND и BUFFER — относительные термы, каж-
дый нз которых определяет внутренний адрес программы, (>;.
нако само выражение (разность между двумя адресами) яв. •
ется величиной абсолютной и определяет длину в байтах :
сти данных, отведенной под буфер.
Значения таких выражений, как BUFEND 4- Bl Fi r
100 — BUFFER или 3 * BUFFER, не представляют ни ; '
лютную величину, ни внутренний адрес программы. Заспск-
мость этих значений от адреса начальной загрузки такова. '
она не имеет связи с чем-либо в самой программе. Поско.г .
маловероятно, чтобы от таких выражений была какая-.,
польза, они рассматриваются как ошибочные.
Для того чтобы определить тип выражения, мы .
иметь информацию о типе всех имен, определенных в пр
ме. Эта информация хранится в таблице имен в вн;' .
знака, определяющего тип значения (абсолютное или °7 ,\с.
тельное). Так, для программы на рис. 2.10 некоторые i
ментов таблицы имен могли бы иметь вид
ИМЯ ТИП ЗНАЧЕНИЕ
RETADR R 0030
BUFFER R 0036
BUFEND R 1036
MAXLEN A 1000
С помощью этой информации ассемблер может легко опрело
лить тип каждого выражения и сгенерировать в объектной
программе записи-модификаторы для относительных выпа-
женнй. 1
В разд. 2.3.5 мы рассмотрим программы, состоящие из не-
скольких частей, каждая из которых может перемещаться не-
зависимо от других. Как мы увидим, в этом случае должны
быть модифицированы правила для определения
жения.
типа выра-
2.3.4. Программные блоки
Во всех примерах, которые мы видели до сих пор, ассемб-
лируемая программа обрабатывалась как единое целое. Хотя
логически исходная программа содержит подпрограммы, обла-
сти данных и т. п., она рассматривалась ассемблером как не-
делимый объект, который переводился в единственный блок
объектного кода. Внутри этой объектной программы сгенериро-
ванные машинные команды и данные располагались в том же
порядке, в котором они были написаны в исходной программе.
Многие ассемблеры предоставляют более гибкие средства
обработки исходной программы и соответствующего ей объект-
ного кода. Одни из этих средств позволяют располагать сгене-
рированные машинные команды и данные в объектной програм-
ме в порядке, отличном от порядка, в котором расположены
соответствующие им исходные предложения. Другие позволяют
создавать несколько независимых частей объектной программы,
Каждая из этих частей сохраняет свою индивидуальность и об-
рабатывается загрузчиком отдельно от других частей. Мы ис-
пользуем термин программные блоки (program blocks) для обо-
значения сегментов, расположенных в пределах одного объект-
ного модуля, и термин управляющие секции (control sections)
для обозначения сегментов, которые транслируются в независи-
мые объектные модули. (Данная терминология, к сожалению,
не является общепризнанной. Фактически в некоторых системах
одни и те же средства языка ассемблера используются для
обеспечения обеих этих логически различных функции.) эт
Разделе мы рассмотрим как используются и обРат^ы°^?Г
ассемблером программные блоки. Разд. 2.3.5 посвящ
Дению управляющих секций. „ЛЛММИыу блоков
На рис. 2.11 показано, как с помощью про гр‘ ‘е ис-
Может быть записана наша программа. В д< поограмм-
иользуются три блока. Первый (непоименов > именем
имй блок содержит выполняемые команды Вьор (
М)ЛТА) содержит все области данных, дли» < 1 состоит
нышаст нескольких слов. Третий (с именемCBLKS) собьем
ИЗ Областей данных, занимающих значительны!
программе
жспий.
С помощью этой информации ассемблер может легко опреде-
лить тип каждого выражения и сгенерировать в объектной
записи-модификаторы для относительных выра-
В разд. 2.3.5 мы рассмотрим программы, состоящие из не-
скольких частей, каждая из которых может перемещаться не-
зависимо от других. Как мы увидим, в этом случае должны
быть модифицированы правила для определения типа выра-
жения.
2.3.4. Программные блоки
Во всех примерах, которые мы видели до сих пор ассемб-
лируемая программа обрабатывалась как единое целое Хотя
логически исходная программа содержит подпрограммы, обла-
сти данных и т. п., она рассматривалась ассемблером как не-
делимый объект, который переводился в единственный блок
объектного кода. Внутри этой объектной программы сгенсриро-
ванные машинные команды и данные располагались в том же
порядке, в котором они были написаны в исходной программе.
Многие ассемблеры предоставляют более гибкие средства
обработки исходной программы и соответствующего ей объект-
ного кода. Одни из этих средств позволяют располагать сгене-
рированные машинные команды и данные в объектной програм-
ме в порядке, отличном от порядка, в котором расположены
соответствующие им исходные предложения. Другие позволяют
создавать несколько независимых частей объектной программы.
Каждая из этих частей сохраняет свою индивидуальность и об-
рабатывается загрузчиком отдельно от других частей. . ы ис
пользуем термин программные блоки {program blocks) для о о-
значения сегментов, расположенных в пределах одног0 ° .
ного модуля, и термин управляющие секции (с пезависи-
Для обозначения сегментов, которые тРаисл"Р] сожалению,
мые объектные модули. (Данная терминол ’ ых системах
не является общепризнанной. ФактичсСх „спол^ьзуются для
ОДНИ и те же средства языка ассемолер^использ^)
обеспечения обеих этих логически р и обрабатываются
Разделе мы рассмотрим как испол у $ посвящен обсуж-
ассемблером программные^ блоки.
Дению управляющих секции. ппМошью программных блоков
На рис. 2.11 показано, как с g данном случае•
может быть записана наша ПР°9 поименованиыи) РР°^еием
Пользуются три блока. Первьп ( коМанды. Второй ( п
Иый блок содержит выполняем х длина котор ’ сОСтонт
СПАТА) содержит все области дань.х • CBLKS сое
нескольких слов. JP значительный
областей данных, за
Строка Исходное предложений
5 COPY START 0 КОПИРОВАНИЕ ФАЙЛА
30- FIRST STL RETADR СОХРАНЕНИЕ АДРЕСА ВОЗВРАТА ВВОД ВХОДНОЙ ЗАПИСИ
15 CLOOP JSU8 RDREC
20 25 LDA COMP LENGTH ♦0 ПРОВЕРКА НА EOF (LENGTH = 0>
30 JEQ ENDFIL ВЫХОД, ЕСЛИ НАШЛИ EOF
33 JSUB WRREC ВЫВОД ВЫХОДНОЙ ЗАПИСИ
40 J CLOOP ЦИКЛ
45 50 ENDFIL LDA' STA -C'EOF' BUFFER ЗАНЕСЕНИЕ МАРКЕРА КОНЦА ФАЙЛА
55 LDA ♦3 УСТАНОВИТЬ LENGTH = 3
60 STA LENGTH
65 JSUH WRREC ЗАПИСЬ EOF
70 J BRETADR ВОЗВРАТ ИЗ ПРОГРАММЫ
92 USE CDATA
95 RETADR RESU 1
100 LENGTH RESW 1 ДЛИНА ЗАПИСИ
103 USE CBLKS
105 BUFFER RESB 4096 ДЛИНА БУФЕРА - 4096 БАЙТ
106 BUFEND EQU * АДРЕС ПЕРВОГО БАЙТА ПОСЛЕ БУФЕРА
107 MAXLEN EQU BUFEND-BUFFEft МАКСИМАЛЬНАЯ ДЛИНА ЗАПИСИ
110 <
115 • ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР
120 *
123 USE
125 RDREC CLEAR X ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА
130 CLEAR A ОБНУЛЕНИЕ РЕГИСТРА А
132 CLEAR S ОБНУЛЕНИЕ РЕГИСТРА S
133 +LDT ♦MAXLEN
135 RLOOP TH INPUT ПРОВЕРКА УСТРОЙСТВА ВВОДА
140 JEQ RLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ
145 RD INPUT ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
150 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ (Х'00')
155 JEQ EXIT ВЫХОД ИЗ ЦИКЛА ПО КОНЦУ ЗАПИСИ
160 STCH BUFFER,X ЗАПИСЬ СИМВОЛА В БУФЕР
165 TIXR T ЦИКЛ ДО ДОСТИХЕНИЯ
170 JLT RLOOP МАКСИМАЛЬНОЙ ДЛИНЫ
175 EXIT STX LENGTH ЗАПОМИНАНИЕ ДЛИНЫ ЗАПИСИ
180 RSUB ВОЗВРАТ ИЗ ПОДПРОГРАММЫ
183 USE CDATA
185 INPUT BYTE X'Fl' КОД УСТРОЙСТВА ВВОДА
195 *
200 • ПОДПРОГРАММА .ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 a
208 USE ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА
210 WRREC CLEAR X
212 LDT LENGTH ПРОВЕРКА УСТРОЙСТВА ВЫВОДА ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОС1И
215 WLOOP TD =X'05'
220 JEQ WLOOP
225 LDCH BUFFER,X ЧТЕНИЕ СИМВОЛА ИЗ БУФЕРА
230 WD =X'05' ВЫВОД СИМВОЛА
235 TIXR T ЦИКЛ, ПОКА НЕ БУДУТ
240 JLT WLOOP ВЫВЕДЕНЫ ВСЕ СИМВОЛЫ
245 RSUB ВОЗВРАТ ИЗ ПОДПРОГРАММЫ
252 USE CDATA
253 LTORG
255 END FIRST
бЛОКЯ&,,,в
i'Hc.’ZJI, Призер программы с несколькими программными
оперативной памяти. Некоторые из возможных доводок „
зу подобного разделения обсуждаются в данном nfw„"OJlb'
Директива ассемблера USE указывает на то кЛио Ця
исходной программы принадлежат к тем или м г CTiI
Вначале предполагается, что все предложения исходноГХ
граммы являются частью непоименованного НтпапД? 1
умолчанию) блока. Если не использовано °н™ оЙоТп'рХже’
НИЯ USE, то считается, что вся программа принадлежит од
му этому блоку. Предложение USE в строке 92 енгиализн X
о начале блока с именем CDATA. К этому блоку относятся
все последующие предложения исходной программы вплоть ю
следующего предложения USE в строке 103, которое начинает
блок с именем CBLKS. Предложение USE может также ука-
зывать на продолжение ранее начатого блока. Так, предложе-
ние в строке 123 продолжает непоименованный блок, а пред-
ложение в строке 183 — блок CDATA.
Как вы видите, каждый блок фактически может содержать
несколько отдельных сегментов исходной программы. Ассемб-
лер перегруппирует (логически) эти сегменты так, чтобы со-
брать вместе отдельные части каждого блока. Затем каждому
из этих блоков будут назначены адреса в объектной програм-
ме в порядке появления блоков в исходной программе. Резуль-
тат будет в точности таким же, как если бы программист соб-
ственноручно перегруппировал предложения исходной програм-,
мы, собрав вместе предложения, принадлежащие каждому из
блоков.
Такая логическая перегруппировка осуществляется ассемб-
лером во время первого просмотра. Для этого с каждым про-г
граммным блоком связывается свой счетчик размещений. При
объявлении нового блока связанный с ним счетчик размещений
устанавливается в 0. Текущее значение, счетчика размещении
сохраняется при переключении на другой блок и восстанавли-
вается, когда возобновляется ранее определенный блок. Таким!
образом, во время первого просмотра каждая метка програм-1
мы получает адрес относительно начала содержащего ос блок а.?
Когда метка заносится в таблицу имен, то вместе с ПР11С151И''
ным ей адресом заносится имя или номер блока, h0T^ 11
она принадлежит. По завершению первого просмотра зна °
счетчика размещений каждого блока указывает на дли у
блока. Затем ассемблер может назначить каж^°^у с'тельч
чальный адрес в объектной программе (начннаг
ВОГОВоДВрееСмя0вТОрого просмотра для генерации «""алре-
ассемблеру для каждого имени нужно л . отноентель-
о/носитель»!© начала объектной программ ‘‘ цочучить из
но начала блока). Эту информацию можно легко по..
Строка Адрес Исходное предложение Обгектнмй код
5 0000 0 COPY START 0
10 0000 • 0 FIRST STL. RETADR 172063
15 0003 . 0 CLOOP JSUB RDREC 4B2021
20 0006 0 LDA LENGTH 032060
25 0009 0 COMP t0 290000
30 000С 0 JEQ ENDFIL 332006
35 0O0F 0 JSUB WRREC 4B203B
40 0012 0 J CLOOP 3F2FEE
45 0015 0 ENDFIL LDA =C'EOF' 032055
50 0018 0 STA BUFFER 0F2056
55 001В 0 LDA ♦3 010003
40 001Е 0 STA LENGTH 0F2048
45 0021 0 JSUB WRREC 4B2029
70 0024 0 J GRETADR 3E203F
92. 0000 1 USE CDATA
95 0000 1 RETADR RESW 1
100 0003 1 LENGTH RESW 1
103 0000 2 USE CBLKS
105 0000 2 BUFFER RESH 4096
106 1000 2 BUFEND EQU *
107 1000 MAXLEN EQU BUFEND-BUFFER
110 Л
115' ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР
120 •
123 0027 0 USE
125 0027 0 RDREC CLEAR X B410
130 0029 0 CLEAR A B400
132 002В 0 CLEAR s B440
133 002D 0 +LDT 4MAXLEN 75101000
135 0031 0 RLOOP TD INPUT E32038
140 0034 0 JEQ RLOOP 332FFA
145 0037 0 RD INPUT DB2032
150 003А 0 COMPR A,S A004
155 003С 0 JEQ EXIT 332008
160 003F 0 STCH BUFFERrX 57A02F
165 0042 0 TIXR T B850
170 0044 0 JLT RLOOP 3B2FEA
175 0047 0 EXIT STX LENGTH 13201F
180 004А 0 RSUB 4F000O
183 0006 1 USE CDATA
185 0006 1 INPUT BYTE X'Fl' Fl
195 >00 • ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 1»
208 0040 0 USE
210 0040 0 WRREC CLEAR X 772017 Е3201В 332FFA 53А016 DF2012
212 215 220 004F 0052 0055 0 0 0 WLOOP LDT TD JEQ LENGTH t=X'05' WLOOP
225 230 0058 005В 0 0 LDCH MD BUFFER,X =X'05'
235 005Е 0 TIXR T 3B2FEF 4F000O
240 0060 0 JLT WLOOP
245 0063 0 RSUB
252 0007 1 USE CDATA
253 0007 1 * LTORG =C'EOf -1 454F46 as
000А 1 * =X'05'
255 END FIRST
Рис. 2.12. Объектный код для программы на рис. 2.11,
SYMTAB: достаточно просто прибавить к адресу метки и™,
ный адрес ее блока. у к 1 нацаль-
от-
На рис. 2.12 показано, как этот процесс применяется к на-
шей модельной программе. В столбце «Адрес» приведены
носительный адрес (внутри блока) каждого предложения и но-
мер соответствующего ему блока (0 = непоименованный блок,
1 = CDATA, 2 = CBLKS). По существу это та же информация,
которая хранится в SYMTAB для каждого имени. Обратите
внимание, что для значения MAXLEN (строка 107) номер бло-
ка не указан. Это означает, что MAXLEN является абсолютной
меткой, значение которой не связано ни с одним из блоков.
В конце первого просмотра ассемблер создает рабочую
лицу, которая содержит начальные адреса и длины всех
ков. Для нашей модельной программы таблица выглядит
таб-
бло-
так:
Имя блока Номер блока Адрес Длина
(непоименованный) 0 оооо 0066
CDATA 1 0066 000 в
CBLKS 2 0071 1000
Рассмотрим теперь команду
20 0006 0 LDA LENGTH 032060
В SYMTAB значение ее операнда (метка LENGTH) определено
как относительный адрес 0003, принадлежащий программному
блоку 1 (CDATA). Начальный адрес CDATA равен 0066. Та-
КИМ ДрРазом’ требуемый целевой адрес для этой команды бу-
дет 0003 + 0066 = 0069. Команда должна ассемблироваться с
использованием адресации относительно счетчика команд. Во
время исполнения данной команды счетчик команд будет со-
держать адрес следующей команды (строка 25). Относитель-
ный адрес этой команды равен 0009 и принадлежит непоимено-
ванному блоку. Поскольку этот блок начинается с адреса 0000,
то, следовательно, значение этого адреса будет просто равно
0009. Итак, требуемое смещение вычисляется: 0069—0009 = 60.
Вычисление других адресов осуществляется аналогично.
Сразу видно, что разделение программы на блоки сущест-
венно уменьшило проблемы адресации. Так как теперь область
памяти, отведенная под буфер большого объема, переместилась
в конец программы, то отпала необходимость в и^а0*1^30ра,'и'
расширенного командного формата в строках 15, 3 , • -
того, отпала надобность в базовом регистре, и мы можем с v
лючить предложения LDB и BASE, которые ранее и
строках 13 и 14. Проблема размещения литералов и Р
зации ссылок на них) также Р^“£а®тсяг нам1/-опдтд для того,
просто включили предложение LTORG в расположены
чтобы быть уверенными, что литералы будут расп
впереди всех областей данных, занимающих значительный
объем памяти.
Конечно, использование программных блоков не дает ничего
такого, что мы не могли бы сделать простым переупорядочива-
нием предложений исходной программы. Например, чтение про-
граммы упрощается, если определения областей данных распо-
лагаются в исходной программе вблизи использующих их
команд. Это особенно справедливо, если программа редактиру-
ется или анализируется с помощью терминала. В больших под-
программах эту задачу (без помощи программных блоков)
можно решить, размещая области данных в удобных местах.
H£0PY л000000л001071
^О0ООООл1Ел172О63л4в2О21л03206Ол290000л332006л4В203ВлЭГ2РЕЕ/р)2055лОГ2О56О1О003
< Т00001EO9OF2O484В2О29ЗЕ2ОЗР
л л л л л
‘^00002 7^ 0^410^400^4 40д7 510 Ю00дЕЗ2038^332F F В 2 0 3 2^А 0 0 4^3 3 2 0 0 8^5 7 АО 2 FyB 8 50
J000044093B2FEA13201F4F0000
Л А Л Л л
( Т0000бСл01Г1
Т00004019^410^7 7 20 17E3201Ba3 32FFAa5 ЗАО 16ADF201 2^88 SO^BZFEF^FOOQO
'TOOOO6DO4454F46O5
Л Л Л А
/ жЬооооо
л
Рис. 2.13. Объектная программа, соответствующая рис. 2.11.
О командах безусловного перехода^ обх’^" позабот"™>'
данных. л для обхода таких областей
желательно1 располагать* Лп?3'1”'0 С машинной точки зрения,
оперативной памяти в оппр?рлриИТЬ1 об ьсктной программы в
НЫ, человеческая логика 1 деленном порядке. С другой сторо-
исходной программы ‘ одсказывает нам, что предложения
ИспользованиеРпрограммнмчЫбРЗСПОЛаГаТЬСЯ В другом П0Ряд,<е-
бов удовлетворяй» РД блоков является одним из спосо-
леРа. Обеспечивагош.г °ИХ/-ЭТИХ тРебова||н» с помощью ассемб-
Для того чтобЛ, "ео0хол"мУ'° реорганизацию.
го блока рядом “^»,е"ИТЬ Ч’Р^'^каждого программно-
сти) ^еорг^анизапии^Р^611110 «обязательно выполнять физиче-
се^блер moS nSX ГеНерИр0ВаНН0Г0 ^ъектного кода. Ас-
генерации вп J, ° зап,,сывать объектный код по мере его
вующий алорг Я ВТ0Р0Г0 просмотра и вставлять соответсг-
здреса загпхпкп лгрУзки в каждую запись тела программы. Эти
ним расположенг । к КуГ ( Z-V наряду с относитель-
яачальный адрес ‘самого ^лпк ДаЛных ВНУТР” блока также "
рис. 2 И ГГпп амого блока. Иллюстрация этому дана на
строк Исходппй срвые записи тела программы генерируются из
строке 92! ветпо. ПР°ГраММЫ с номерами с 5 до 70 Когда в
р чается предложение USE, ассемблер записывает
2.3. Машинно-независимые характеристики ассемблер*
текущую запись тела программы (хотя в ней еще есть свобод-
ное место). Затем ассемблер подготавливается к открытию но-
вой записи тела программы для нового программного блока.
Однако ввиду того, что предложения в строках с 95 по 105
не приводят к генерации объектного кода, не создается и соот-
ветствующих им записей тела программы. Следующие две
Исходная программа
Программа, загружаемая
Объектная программа в память
после выполнения ассемблиро-
блоки для рис. 2.11
Рис. 2.14. Программные
вания и загрузки.
записи тела программы получаются из строк 125—180. На этот
раз предложения, принадлежащие очередному программному
блоку, действительно требуют генерации объектного кода. Пя-
тая запись тела программы содержит один-единственный байт
данных, генерируемый из строки 185. Шестая запись тела про-
граммы возобновляет непоименованный блок, и оставшаяся
часть объектной программы обрабатывается таким же образом.
То, что записи тела программы расположены в объектной про-
грамме нс в порядке возрастания адресов, не имеет значения.
Загрузчик просто помещает каждую запись по указанному
адресу. По завершению загрузки сгенерированный код непо-
именованного блока будет занимать относительные адреса с
0000 по 0065; сгенерированный код и зарезервированные обла-
сти данных блока CDATA будут занимать адреса с 0066 по
0070, а память, зарезервированная для CBLKS, будет занимать
адреса с 0071 по 1070. На рис. 2.14 прослежен процесс ассемб-
лирования и загрузки блоков нашей модельной программы.
Обратите внимание на то, что предложения программы, обозна-
ченные CDATA(1) и CBLKS(l), фактически не присутствуют
в объектной программе. Резервирование памяти для этих об-
ластей обеспечивается автоматически при загрузке программы
с помощью механизма назначения адресов.
Для того чтобы убедиться, что вы поняли, как ассемблер
обрабатывает программы, состоящие из нескольких блоков, вам
следует тщательно изучить сгенерированный код (рис. 2.12) и
выполнить ассемблирование еще нескольких команд. А чтобы
уяснить, как различные части каждого программного блока
собираются вместе, вам следует также воспроизвести (вручную)
загрузку объектной программы, приведенной на рис. 2.13.
2.3.5. Управляющие секции и связывание
программ
В этом разделе мы обсудим, как обрабатываются програм-
мы, состоящие из нескольких управляющих секций. Управляю-
щая секция — это часть программы, которая после ассемблиро-
вания сохраняет свою индивидуальность и может загружаться
и перемещаться независимо от других. В отдельные управляю-
щие секции чаще всего выделяются подпрограммы или другие
логические подразделы программы. Программист может отдель-
но ассемблировать и загружать каждую из таких управляющих
секций. Достигаемая за счет этого гибкость является основным
преимуществом их использования. Примеры этого будут рас-
смотрены в гл. 3, когда мы будем обсуждать редакторы связен.
Поскольку управляющие секции образуют логически связан-
ные части программы, то, следовательно, необходимо предос! а-
вить некоторые средства для их связывания (Unking) ДРУ1 L
другом. Например, команды одной управляющей секции долж-
ны иметь возможность ссылаться на команды или области дан-
ных, расположенные в другой секции. Такие ссылки нельз»
обрабатывать обычным образом, поскольку управляющие сек-
ции загружаются и перемещаются независимо друг от друга и
ассемблеру ничего не известно о том, где будут расположены
другие управляющие секции во время исполнения програм-
мы. Такие ссылки между управляющими секциями называюкя
внешними ссылками (external references) пля
ней ссылки ассемблер генерирует информацию, котопая”1!,»"''
возможность загрузчику выполнить требуемое связыХ?» ’п
грамм. В этом разделе мы опишем, как наш ассемблер об?а‘
батывает внешние ссылки. Реальное выполнение связывХ
будет детально обсуждаться в гл. 3. связывания
На рис. 2.15 показано, как наша модельная программа мо-
жет быть записана в виде нескольких управляющих'секций
В данном случае имеются три управляющие секции- одна для
главной программы и по одной для каждой из подпрограмм
Предложение START определяет начало ассемблируемой поо-
граммы и задает имя (COPY) первой управляющей секции.
Первая секция расположена вплоть до предложения CSECT в
строке 109. Эта директива ассемблера сигнализирует о начале
повой управляющей секции с именем RDREC. Аналогично пред-
ложение CSECT в строке 193 начинает управляющую секцию
с именем WRREC. Для каждой управляющей секции ассемблер
заводит отдельный счетчик размещений (начинающийся с 0)
точно так же, как он это делает для программных блоков.
От программных блоков управляющие секции отличаются
тем, что они обрабатываются ассемблером независимо друг от
друга. (Необязательно даже, чтобы все управляющие секции
программы ассемблировались одновременно.) Имена, определен-
ные в одной управляющей секции, не могут непосредственно ис-
пользоваться в другой секции. Для того чтобы загрузчик смог
их обработать, они должны быть описаны как внешние ссылки.
На рис. 2.15 показаны две директивы ассемблера для задания
таких ссылок: EXTDEF (определение внешних имен) и EXT-
REF (объявление внешних ссылок). Предложение EXTDEI-
определяет имена, описанные в данной управляющей секции,
но доступные для использования в других секциях. Такие име-
на называются внешними именами {external symbols). Имена
управляющих секций (в данном случае COPY, RDREC и
WRREC) определять в предложении EXTDEF не требуется,
так как они автоматически считаются внешними. Предложение
EXTREF объявляет имена, которые используются в данной уп-
равляющей секции, но определены где-либо еще. Например,
имена BUFFER, BUFEND и LENGTH, определенные в управ-
ляющей секции с именем COPY, делаются доступными др} г
секциям с помощью предложения EXTDEr в ^tj •
В третьей управляющей секции (WRREC), согласи Р -•
жению EXTREF (строка 207), используются два внеш ц
имени. Порядок перечисления имен в предложениях
EXTREF несуществен. ассемблер
Теперь мы готовы к тому, чтооы посмотр > КдЖД0Г0 пред-
обрабатывает внешние ссылки. На рис. 2.1 д б KTHblg код.
ложения программы показан сгенерирован!
Сорока
Исходное предложение
5 6 COPY START EXTDEF 0 КОПИРОВАНИЕ ЛЛЙЛЛ BUFFER, BUFEND, LENGTH *****
Z FIRST CLOOP EXTREF RDREC,WRREC
10 15 20 25 STL +JSUB LDA COMP RETADR RDREC LENGTH #0 Е2™АНЕНИЕ алреСА возврата ВВОД ВХОДНОЙ ЗАПИСИ ПРОВЕРКА НА EOF <LENGTH = в)
30 35 40 ENDFIL JEQ +JSUB J ENDFIL WRREC CLOOP ВЫХОД, ЕСЛИ НАШЛИ EOF ВЫВОД ВЫХОДНОЙ ЗАПИСИ цикл
45 50 •LDA STA *=C'EOF' BUFFER ЗАНЕСЕНИЕ МАРКЕРА КОНЦА ФАЙЛА
55 60 LDA STA ♦3 LENGTH УСТАНОВИТЬ LENGTH = 3
65 ♦JSUB WRREC ЗАПИСЬ EOF
70 95 RETADR J RESW PRETADR 1 ВОЗВРАТ ИЗ ПРОГРАММЫ
100 LENGTH RESW 1 ДЛИНА ЗАПИСИ
103 • LTORG
105 BUFFER RESB 4096 ДЛИНА БУФЕРА - 4096 БАЙТ
106 BUFEND EQU *
107 MAXLEN EQU BUFEND-BUFFER МАКСИМАЛЬНАЯ ДЛИНА ЗАПИСИ
109 RDREC CSECT
110 •
115 • ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР
120 w
122 EXTREF BUFFER,LENGTH.BUFEND
125 CLEAR X ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА
130 CLEAR A ОБНУЛЕНИЕ РЕГИСТРА А
132 CLEAR S ОБНУЛЕНИЕ РЕГИСТРА S
133 LDT MAXLEN
135 RLOOP TD INPUT ПРОВЕРКА УСТРОЙСТВА ВВОДА
140 JEQ RLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ
145 RD INPUT ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
150 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ (Х'00'>
155 JEQ EXIT ВЫХОД ИЗ ЦИКЛА ПО КОНЦУ ЗАПИСИ
160 +STCH BUFFERS ' ЗАПИСЬ СИМВОЛА В БУФЕР
165 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ
170 JLT RLOOP МАКСИМАЛЬНОЙ ДЛИНЫ
175 EXIT +STX LENGTH ЗАПОМИНАНИЕ ДЛИНЫ ЗАПИСИ
180 RSUB ВОЗВРАТ ИЗ ПОДПРОГРАММЫ
185 INPUT BYTE X'Fl' КОД УСТРОЙСТВА ВВОДА
190 MAXLEN WORD BUFEND-BUFFER
193 WRREC CSECT
195
200 • ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 •
207 EXTREF LENGTH,BUFFER ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА
210 CLEAR X
212 ♦LDT LENGTH ПРОВЕРКА УСТРОЙСТВА ВЫВОДА
215 WLOOP TD -X'05z
220 JEQ WLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ
225 ♦LDCH BUFFERrX ЧТЕНИЕ СИМВОЛА ИЗ БУФЕРА
230 WD =X'05Z ВЫВОД СИМВОЛА
235 TIXR T ЦИКЛ, ПОКА НЕ БУДУТ
240 JLT WLOOP ВЫВЕДЕНЫ ВСЕ СИМВОЛЫ
245 RSUB ВОЗВРАТ ИЗ ПОДПРОГРАММЫ
255 END FIRST
Рис, 2,15, Иллюстрация
управляющих
секций и связывания программы.
Строна Адрёс Исходное предложение
5 0000 COPY START 0 О^ектиий год
6 7 10 0000 FIRST EXTDEF EXTREF STL buffer.dufend,length RDREC,WRREC RETADR
15 0003 ' CLOOP 4 JSUB RDREC 172027
•20 0007 ' LDA LENGTH 4610000^
25 000А COHP ^-*"*1 TW III f0 032023
-30 35 000ГГ 0010 JEQ 4 JSUB ENDFIL URREC 290000 332007
40 0014 J CLOOP AB100000
45 0017 ENDFIL LDA t=C'EOF' 3F2FEC
Ь0 55 001А 0010 STA LDA BUFFER ♦3 032016 CF2016
60 65 70 0020 0023 0027 STA 4 JSUB J LENGTH WRREC PRETADR 010003 0F200A 40100000 3E2000
95 002А RETADR RESU 1
100 0020 LENGTH RESU 1
103 LTORG
105 0030 0033 w SUFFER -C'EOF' RESH f 4096 454F4&
106 1033 BUFEND EQU EQU * *
107 1000 MAXLEN bufend-buffer
109 0000 RDREC CSECT
110
115 ПОДПРОГРАММА ВВОДА ЗАПИСИ НА ВУФеЬ
120 at
122 EXTREF BUFFERiLENGTH,BUFEND
125 0000 CLEAR X B410
130 0002 CLEAR A B400
132 0004 CLEAR S B440
133 0006 LDT MAXLEN. 77201F
135 0009» RLOOP TD INPUT E3201B
140 000С JEQ * RLOOP 332FFA
145 000F RD INPUT DB2015
150 0012 COMPR A,S A004
155 0014 JEQ EXIT 332009
160 0017 4STCH BUFFER,X 57900000
165 001В TIXR T B850
170 001В JLT RLOOP 3B2FE9
175 0020 EXIT 4STX LENGTH 33100000
180 00^4 RSUB 4F0000
185 0027 INPUT BYTE XZF1' Fl
190 0028 MAXLEN WORD bufend-buffer 000000
193 0000 URREC CSECT
195 200 M « ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 207 • EXTREF LENGTH,BUFFER B410 77100000 E32012
210 212 0000 0002 CLEAR +LDT X LENGTH
215 0006 «LOOP TD --X 05 332FFA
220 0009 JEQ WLOOP 53900000
225 000С +LDCH BUFFER,X DF2008
230 0010 WD -X 05 S850
235 0013 TIXR T 3B2FEE
240 0015 JLT WLOOP 4F0000
245 0018 RSUB FIRST
255 001В * END =X'05' 05
Рис, 2.16, Объектный код для программы на рис, -.ы.
Для начала рассмотрим команду
15 0003 CLOOP +JSUB RDREC 4В100000
Ее операнд (RDREC) объявлен в предложении EFTRFF ,,
следовательно, это внешняя ссылка. Ассемблеру ничего н’рч ’
A—^^DrTc бУДСТ 3аГРУжена У”Р-ляюРщУая
держащая RDREC, и поэтому он не может обработать ашое
ную часть данной команды. Вместо этого он устанавливает
шуюСрмЩНЫМ 0 " передает загрузчику информацию, позволяю-
щую ему занести во время загрузки нужный ад-)ес Поскоику
неизвестно, будет ли адрес RDREC взаимосвязан с чем-либо в
данной управляющей секции, относительную адресацию неволь-
зовать нельзя. Следовательно, для того чтобы иметь достаточно
места для занесения фактического адреса, необходимо исполь-
зовать расширенный командный формат. Это
любой команды, операнд которой ссылается
Аналогично в команде
справедливо для
на внешнее имя.
160 0017 +STCFI BUFFER,X 57900000
имеется внешняя ссылка на метку BUFFER.
Эта команда ас-
семблируется с использованием расширенного командного фор-
мата и нулевым адресом. Разряд х установлен в 1, что явля-
ется признаком индексной адресации. Предложение
190 0028 MAXLEN WORD BUFEND - BUFFER 000000
лишь незначительно отличается от предыдущих. Здесь значение
генерируемой 1-словной константы определяется с помощью
выражения, в котором используются две внешние ссылки:
BUFEND и BUFFER. Как и ранее, ассемблер заносит для
этой константы нулевое значение. Загрузчик во время загруз-
ки прибавит к этому значению адрес метки BUFEND, а затем
вычтет из него адрес BUFFER, что и даст в итоге требуемое
значение.
Укажем на различие в обработке выражения в строке 190
и похожего выражения в строке 107. Имена BUFEND и
BUFFER определены в той же управляющей секции, что и
предложение EQU в строке 107. Поэтому значение этого выра-
жения может быть вычислено непосредственно ассемблером.
Для строки 190 это сделать нельзя, так как BUFEND и BL
FER определены в другой управляющей секции и, следоваве.п>
но, во время ассемблирования их значения неизвестны.
Как видно из предыдущих рассуждений, ассемблер дол*1
запоминать (в SYMTAB), в какой управляющей секции бы.'
определено то или иное имя. Любая попытка использовать in
из другой управляющей секции должна отмечаться
если только это имя не объявлено (с помощью ЕХТИГл
качестве внешнего. Ассемблер должен разрешать использеи а
одинаковые имена в разных управляющих секциях и
противоречивые определения MAXLEN в стооках in? Pinnep’
должны вызвать никаких проблем. Ссылки на MAXIpn не
равняющей секции COPY 'будут использовать определен,^ „
строке 107, тогда как ссылки в RDREC — определение о стро.
До сих пор мы видели, что ассемблер оставляет место в
объектном коде для занесения значений внешних имен. Кроме
того, он должен включить в объектную программу информа
цию, позволяющую загрузчику занести необходимые значения
туда, куда требуется. Для этого нам необходимо видоизменить
структуру записи-модификатора и ввести два новых типа
записей. Как и раньше, конкретный формат этих записей мо-
жет быть произвольным, однако в любом случае эта информа-
ция должна в той или иной форме передаваться загрузчику.
Два новых типа записей — это запись-определение и запись-
ссылка. Запись-определение содержит информацию о внешних
именах, определенных в данной управляющей секции, т. е. име-
нах, объявленных в EXTDEF. В записи-ссылке содержится
список имен, используемых в данной управляющей секции в
качестве внешних ссылок, т. е. имен, объявленных в EXTREF.
Ниже приводятся форматы этих записей.
Запись-определение:
Столбец 1
Столбцы 2 — 7
Столбцы 8—13
Столбцы 14 — 73
Запись-ссылка:
Столбец 1
Столбцы 2 — 7
D.
Идентификатор внешнего имени, опреде-
ленный в данной управляющей секции.
Относительный адрес имени (шестнадца-
теричный).
Информация, аналогичная столбцам 2—
13 для других внешних имен.
Идентификатор внешнего имени, на кото-
рый есть ссылка в данной управляющей
8-73
Столбцы
Секции. 9—7
Информация, аналогичная столбцам
для других внешних имен.
Другая информация, не0^х0^ая Для„овыТ’фо^ма^показа^
добавляется в запись-модификатор. Ее но ф 1
ниже.
Запись-модификатор:
Столбец 1
Столбцы 2 — 7
Начальный адрес
атсрнчпый).
Столбцы 8 — 9
Столбец 10
Столбцы 11 — 16
Длина модифицируемого адресного поля
в полубайтах (шестнадцатеричная)
Признак модификации (-|- или —-)
Внешнее имя, значение которого надо
добавить к заданному полю или вычесть
из него.
Первые три
поля этой записи остались без изменений. Два но-
вых поля определяют тип требуемой модификации: сложение
или вычитание значения внешнего имени. Имена, используемые
для модификации, могут быть определены как в данной управ-
ляющей секции, так и в другой. '
Па рис, 2.17 показана объектная программа, соответствую-
щая исходному тексту рис. 2.16. Обратите внимание, что для
каждой управляющей секции имеется отдельный набор записей
объектной программы (от записи-заголовка до записи-конца).
Записи каждой управляющей секции в точности такие же, как
если бы эти секции ассемблировались раздельно.
Записи-определения и записи-ссылки каждой управляющей
секции содержат имена, объявленные в предложениях EXTDEF
и EXTREF. Запись-определение содержит, кроме того, относи-
тельный адрес каждого внешнего имени внутри данной управ-
ляющей секции. Для имен, объявленных в EXTREF, информа-
ции об адресах нет. Эти имена просто перечисляются в запи-
си-ссылке.
Давайте теперь изучим процесс связывания внешних ссылок,
начиная с ранее рассмотренных исходных предложений. Поле
адреса команды JSUB в строке 15 начинается с относительно-
го адреса 0004. В объектной программе его начальное значе-
ние равно 0. Запись-модификатор
М00000405 + RDREC
управляющей секции COPY определяет, что адрес метин
RDREC должен быть прибавлен к этому полю, что и даст тре-
буемый машинный адрес. Две другие записи-модификаторы в
секции COPY выполняют сходные функции для команд в стро-
ках 35 и 65. Аналогично первая запись-модификатор в управ-
ляющей секции RDREC указывает на занесение внешней ссылки
для строки 160.
Обработка 1-словной константы, сгенерированной по стром
190, мало чем отличается от ранее описанного процесса. Зиа
чением этой константы является выражение BUFEND^ В-.
FER, где обе метки определены в другой управляющей секим
Ассемблер генерирует эту константу (расположенную по отн*>
сительному адресу 0028 в управляющей секции RDREC) с ।
левым начальным значением. Две последние записи-модифик-1
торы в RDREC требуют, чтобы адрес BUFEND был добавлю
к указанному полю, а адрес BUFFER
ления выполняются во время загрузки,
ется требуемая константа.
- I
был вычтен. Эти вычис*
и в результате получа-
НДСОР¥ ^00000^00103 3
J)aBUFFERa0000 3 3ABUFEN£^OOlO3 3ALENGTH/pOOO2D
l^RDREC aWRREC
TA000000A1DA1 72027A4B100000A03202V90000A332007A4B1QOOOOA3F2FEC0320140F2016
Ta00001DaODa01000 3aOF200A4B100000a3E2000
л ЛЛ л л л
Та00003(^03л4 5 4 F4 6
>^0000040 5 + RDR ЕС
мдоооо1 iaosa+wrrec
MOOOO24O5+WRREC
л л л
ЕОООООО
Л
H^DREC ^00000^00020
RaBUFFEI^ENGTHaBUFEND
Тл000000л1 DaB4 ЮЛВ4ООЛВ440^77 201 F^E3201 ВлЗ.32FF^DB201 5/00^332009д57900000^8 50.
Т00001 D0E3B2FE9 1 3 1000004F0000J kOQQOQQ
л л л л л Л Л
М.ОООО 1 8a05a+BUFFER
Нд00002 1^5 + LENGTH*
Мл000028л06л+BUFEND
Mp00028A06A-BUFFER
Е
HWRREC ^0000(^000010
^LENCT^BUFFER’
мроо001^05 +В OFFER
Е
ис. 2.17. Объектная программа, соответствующая рис. 2.15.
Р ГЛ' $ мы Детально рассмотрим, как загрузчик выполняет
данные модификации; сейчас же важно, чтобы вы доскональ-
но разобрались с концепциями процесса связывания. Вам сле-
дует тщательно изучить другие записи-модификаторы на
рис. 2.17 и самостоятельно реконструировать их генерацию по
предложениям исходной программы.
Обратите внимание, что измененная запись-модификатор мо-
жет по-прежнему использоваться для перемещения программ.
В случае перемещения модификация заключается в добавлении
начального адреса управляющей секции к определенным полям
в объектной программе. Значением имени, исполу™,
честве названия управляющей секции, является требуемый аТ
рес. Поскольку имя управляющей секции автоматически явл£
быть использовано в
ется внешним именем, то оно может
записи-модификаторе. Так, например,
рис. 2.8
М00000705
М00001405
М00002705
будут заменены на записи-модификаторы
М00000705 + COPY
М00001405 + COPY
М00002705 4- COPY
записи-модификаторы
вида
Таким образом, один и тот же механизм может быть использо-
ван как для перемещения программ, так и для их связывания.
В следующей главе будет рассмотрено еще несколько примеров'.
Наличие нескольких управляющих секций, каждая из кото-
рых может перемещаться независимо от других, создает допол-
нительные трудности при обработке выражений. Ранее мы тре-
бовали, чтобы все относительные термы выражения группиро-
вались в пары (для абсолютного выражения) или чтобы все
относительные термы, кроме одного, группировались в пары
‘(для относительного выражения). Теперь мы вынуждены уси-
лить эти ограничения и потребовать, чтобы парные термы при-
надлежали одной управляющей секции. Причина этого про-
ста— если оба терма определяют относительные метки в од-
ной и той же управляющей секции, то их разность является
абсолютной величиной (независимо от того, где будет располо-
жена управляющая секция). С другой стороны, если метки
относятся к различным управляющим секциям, то значение их
разности заранее непредсказуемо (и потому, вероятно, беспо-
лезно). Например, выражение BUFEND — BUFFER определя-
ет длину буфера в байтах. С другой стороны, выражение
RDREC — COPY определяет разность между адресами загруз-
ки двух управляющих секций. Эта величина зависит от способа
размещения программы в оперативной памяти, и маловероягп >,
чтобы она была полезна в прикладных программах.
Когда в выражении используются внешние ссылки, ассо"^
лер в общем случае не может определить, корректно оно и- >
нет. Группировка относительных термов для проверки коррск^
ности не может быть сделана, если не известно, какие тор
принадлежат одной секции, а во время ассемблирования
информация отсутствует. В этом случае ассемблер вычисл 1
все известные ему термы и комбинирует их так, чтобы ча -
чпть начальное значение вьтпл^оттисг i/n
записи-модификаторы, позволяющие ^грузчпг?’4°" гепеРиРУ«
числение. Загрузчик мпч-п-г „Jr загрузчику закончить вы-
выражения. ВеТэ™eoTpte" мТо^м'^Г3 „“о"0™
связывающего загрузчика. У гл‘ 3 При изУчении
2.4. Варианты построения ассемблеров
В этом разделе мы рассмотрим несколько важных вариан-
тов общей схемы ассемблирования. Во многих случаях про-
граммист не ощущает прямого воздействия схемы ассембчиро-
вания на возможности, предоставляемые языком асссмбпера
хотя иногда действительно имеются побочные эффекты кото-
рые следует принимать во внимание.
В разд. 2.4.1 мы опишем оверлейную структуру, которая
обычно используется для двухпросмотровых ассемблеров.
В разд. 2.4.2 и 2.4.3 обсуждаются две альтернативные (по от-
ношению к стандартной двухпросмотровой) схемы ассемблиро-
вания. В разд. 2.4.2 описываются структура и алгоритм одно-
просмотрового ассемблера. Такие ассемблеры используются там,
где желательно или даже необходимо обойтись без второго
просмотра исходной программы. В разд. 2.4.3 дается представ-
ление о многопросмотровых ассемблерах. В этих ассемблерах
получает свое дальнейшее развитие двухпросмотровая схема
ассемблирования, что позволяет обрабатывать ссылки вперед в
предложениях определения имен.
2.4.1. Двухпросмотровый ассемблер с
оверлейной структурой
Как мы видели, в большинстве ассемблеров процесс обра-
ботки исходной программы делится на два просмотра. Внут-
ренние таблицы и подпрограммы, которые используются только
во время первого просмотра, становятся ненужными после его
завершения. Многие подпрограммы и таблицы используют
только для одного просмотра и никогда не трсоуются для > ру
того. В то же время некоторые ользуются
и подпрограммы (например, поиск в S^MTA )
В °НаИХр?1РсО2Мг,8ТРпредставлена общая структура ^^poc^
вого ассемблера. Этот ассемблер состоит из Р _ уп_
образующих дерево. Корневой сегмент сод Р’ р поочеред-
равляющую программу, функцией и Просмотр 2).
ный вызов двух других сегментов <Прос Р гоам„ы необхо-
Корневой сегмент содержит таблицы и под р Р
димые для обоих просмотров.
Поскольку сегменты Просмотр 1 и Просмотр 2 никогда не
1РоЛтЮТСЯ одновРсме,,но’ то во время работы ассемблера они
Вначалр"йМп1м °ЛН° " ™ Ж<? пРостРанство оперативной памяти.
Вначале в память загружается корневой сегмент и сегмент
Сегмент
Просмотр 1
Сегмент
Просмотр 2
Рис. 2.18. Структура двухпросмотрового ассемблера.
Просмотр 1, и ассемблер выполняет первый просмотр. После
его завершения на место сегмента Просмотр 1 загружается
Максимальная
память, тре-
буемая при
оверлейной
загрузке
Объем
памяти,
занимаемый
всеми под-
программами
и таблицами
ассемблера
Управляющая
программа
Управляющая
программа
Общие
таблицы
и подпрог-
раммы
Резидентная
часть
Общие
таблицы
и подпрог-
раммы
Подпрог-
раммы
первого
просмотра
Таблицы
первого
просмотра
Загружаются
на одно и то
же место
в оперативной
памяти
Подпрог-
раммы
второго
просмотра
Таблицы
второго
просмотра
Рис. 2.19. Двухпросмотровый ассемблер с оверлейной стр}М)рой.
сегмент Просмотр 2. После этого ассемблер выпо^*1Я^У,ТоЧНого
просмотр ассемблируемой программы (или пр . у 11а
файла) и завершает свою работу. Этот процесс 4 рК1!-
рис. 2.19. Обратите внимание, что при использовании и г
ной структуры ассемблеру требуется значит ел >
оперативной памяти, чем если бы одновременно sarnv~.
сегменты обоих просмотров. Во многих двухпросмотпп^’’
ассемблерах этот прием используется для сокращая
мого объема оперативной памяти. ^ния требус-
Программа, построенная подобным образом, называется
оверлейной программой или программой с перекрытиемтю-
как во время ее исполнения некоторые из ее сегментов пепс'
крывают другие. В гл. 3 мы более подробно обсудим оветей
ные программы и рассмотрим, как они обрабатываются загруз
чипом и сервисными процедурами операционной системы
2.4.2. Однопросмотровые ассемблеры
В этом разделе мы рассмотрим структуру и проектирование
однопросмотровых ассемблеров. Как мы отмечали в разд. 2 1
основная трудность, возникающая при попытке ассемблировать
программу за один просмотр, связана со ссылками вперед. Ча-
сто в качестве операндов команд используются имена, которые
еще не были определены в исходной программе. Поэтому ас-
семблер не знает, какие адреса занести в транслируемую про-
грамму.
Довольно легко исключить ссылки вперед на данные; до-
статочно потребовать, чтобы все области данных определялись
в исходной программе раньше, чем появляются команды, кото-
рые на них ссылаются. Это не слишком жесткое ограничение.
Программист просто размещает все области данных в начале
программы, а не в конце. К несчастью, невозможно столь же
легко исключить ссылки вперед на метки команд. Логика про-
граммы часто требует передачи управления вперед. (Напри-
мер, выход из цикла после проверки некоторого условия.) Тре-
бование исключить все такие передачи управления оказалось
бы гораздо более жестким и неудобным. Поэтому ассемблер
должен предпринимать специальные меры для обработки
ссылок вперед. Однако для того, чтобы облегчить задачу, мно-
гие однопросмотровые ассемблеры действительно запрещай)?
(или по крайней мерс не рекомендуют) ссылки вперед на
данные. ,
Существует два основных типа однопросмотровых ассем >-и -
ров. Ассемблеры первого типа записывают объектны f к<>л 111
посредственно в оперативную память для немедленною испол
нения; ассемблеры второго типа создают объектную пр(»грам
му, которая будет выполняться позднее. Обсуждение > •
типов мы проиллюстрируем с помощью программы на рис. •
Это тот же самый пример, что и на рис. 2.2, но все о | . • _
данных расположены перед командами, в которых oi
зуются. Сгенерированный объектный код показан i. Р _
только для справки. Мы обсудим, как однопросмотровыи
Строка Адрес Исходное предложение Объектный код
0 1000 COPY START 1000
1 2 3 1000 1003 1006 EOF THREE ZERO BYTE WORD WORD C'EOF' 3 0 454F46 000003 000000
4 1009 RETADR RESW 1
5 100С LENGTH RESW 1
6 9 100F BUFFER RESB 4096
10 200F FIRST STL RETADR 141009
15 2012 CLOOP JSUB RDREC 48203D
20 2015 LDA LENGTH 00100C
25 2018 COMP ZERO 281006
30 2018 JEQ ENDFIL 302024
35 201Е JSUB WRREC 482062 3C2012
40 2021 J CLOOP
45 2024 ENDFIL LDA EOF 001000
50 2027 STA BUFFER 0C1O0F
55 202А LDA THREE 001003
60 202D STA LENGTH 0C100C
65 2030 JSUB WRREC 482062.
70 2033 LDL RETADR 081009
75 2036 RSUB 4C000&
110 »
115 • ПОДПРОГРАММА ВВОДА ЗАПИСИ НА ВУФЕР
120
121 2039 INPUT BYTE ' X'Fl' Fl
122 203А MAXLEN WORD 4096 001000
124 041006
125 203D RDREC LDX ZERO
130 2040 LDA ZERO 001006
135 2043 RLOOP TD INPUT E02039
140 2046 JEQ RLOOP 302043
145 2049 RD INPUT D82039
150 204С COMP ZERO 281006
155 204F JEQ EXIT 30205B
160 2052 STCH BUFFER,X 54900F
165 2055 TIX MAXLEN 2C203A
170 2058 JLT RLOOP 382043
175 180 205В 205Е EXIT STX RSUB LENGTH 10100C 4C0000
195 200 M ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 206 2061 OUTPUT BYTE X'05' 05
205 210 2062 WRREC LDX ZERO 041006 E02061 302065 50900F DC2061 2C100C 392065
215 2065 WLOOP TD OUTPUT
220 2068 JEQ WLOOP
225 230 235 206В 206Е 2071 LOCH WD TIX BUFFER,X OUTPUT LENGTH
240 2074 JLT WLOOP 4C0000
245 2077 RSUB FIRST
255 END >
Рис. 2.20. Модельная программа для однопросмотрового асам*>.к|
ассемблер каждого типа мог бы в действителт
вать требуемую объектную программу °СТИ сгенеР"Ро-
Вначале мы рассмотрим однопросмотровые ассомПп™
генерирующие объектный код непосредственно в onepS
память для немедленного исполнения. В этом случаенесоэ™
ется объектная программа и не требуется загрузчик Такие
ассемблеры типа загрузка — выполнение полезны в системах
ориентированных на разработку и тестирование программ Ти’
личным примером такой системы может служить университет-
ская студенческая система. В такой системе значительную юлю
от общего объема работы составляет трансляция программ.
Поскольку практически при каждом новом запуске программ
происходит их переассемблироваиие, эффективность процесса
ассемблирования приобретает важное значение. Ассемблеры
типа загрузка — выполнение позволяют избежать накладных
расходов, связанных с записью объектной программы на внеш-
нюю память и ее последующим считыванием. Такой процесс
может быть организован как однопросмотровым, так и
двухпросмотровым ассемблером. Однако однопросмотровый
ассемблер позволяет избежать также и накладных расходов,
связанных с дополнительным просмотром исходной про-
граммы.
Поскольку генерируемая объектная программа вместо того,
чтобы записываться на внешнюю память, располагается в опе-
ративной памяти, то обработка ссылок вперед оказывается ме-
нее сложной. Ассемблер просто генерирует команды объектного
кода по мере просмотра исходной программы. Если операндом
команды является еще неопределенное имя, то при ассемблиро-
вании команды обработка ее адресной части пропускается.
Имя, использованное в качестве операнда, заносится в таблицу
имен (если оно не было занесено ранее). Строка таблицы по-
мечается признаком, указывающим на то, что данное имя еще
не определено. Адрес операндного поля команды, ссылающейся
на неопределенное имя, добавляется в список ссылок вперед,
связанный с соответствующим элементом таблицы имен. Если
встречается определение имени, то просматривается его список
ссылок вперед (если он есть) и требуемый адрес заносится в
каждую предварительно сгенерированную команду.
Рассмотрим пример, который поможет прояснить этот р
цесс. На рис. 2.21а показано, как будут выглядеть объектный
код и элементы таблицы имен после просмотра стр 4
программы на рис. 2.20. Первая ссылка вперед была в стро
кс 15. Поскольку операнд (RDREC) еще не »ылопред&1№,го
команда ассемблировалась без назначения адр 3 ' м ,1МЯ
операнда (на рисунке обозначено как „«прппнное имя
RDREC было занесено в SYMTAB как »еолРеде"“НО(С2о"з)
(обозначено .), а адрес операндного поля команды (
Адрес,
памяти
1000
1010
2000
2010
2020
Содержимое
454F4600 ХХХХХХХХ 00030000 хххххххх 00ХХХХХХ ХХХХХХХХ хххххххк ХХХХХХХХ
хххххххх 100948 — —зешз ХХХХХХХХ —0Q1QQC хххххххх 28100630 xxxxxxbl —*•-48—
а
Имя Значение
Адрес
памяти
......
1000
1010
♦
«*
454F4600
хххххххх
Содержимое_____________
00030000 ООхХХХХК хххххххх
хххххххх хххххххх хххххххх
Имя Значение
2000
2010
2020
.2030
2040
2050
хххххххх
10094820
—ЗС2012
48-—— 08
QO1006EO
—*5490
хххххххх
3D00100C
ооюооос
10094С00
2O39302Q
QF
ХХХХХХХХ
28100630
100Г0010
00F1001Q
43DS2039
ХХХХХХ14
202448—
030C100C
00041006
281QQ630
length 1 ooc
RDREC >03D
THREE 1003
ZERO 1006
WRREC * |*T —►) 201F [*]—»( 2031 ,1 >
EOF 1000 I
ENDFlL retadr 2024 I 1009 '
1 BUFFER 100F
j CLOOP 2012
|FIRSr 200P
["maxlen 203A
pNPUV 2039
1 EXIT *1' ^|2050 [ 0 J
Г RLOOP' 2043
6
2.21. Объектные коды, записанные в оперативную память, 11
просмотра строки 40(a) и строки 160 (б) проч ‘
Рис. _
менты таблицы имен после
мы на рис, 2.20,
был занесен в список, связанный с RDREC. Аналогично ойм
батывались команды в строках 30 и 35. 1
Рассмотрим теперь рис. 2.216, соответствующий ситуации
после просмотра строки 160. К этому моменту была разреше-
на часть ссылок вперед, в то время как другие были добавле-
ны. Когда было определено имя ENDFIL (строка 45), ассемб-
лер занес его значение в SYMTAB. Затем он занес это значе-
ние в операндное поле команды (по адресу 201С), как это
предписано списком ссылок вперед. С этого момента все ссыл-
ки на ENDFIL пе будут являться ссылками вперед и не будут
заноситься в список. Аналогично определение RDREC (стро-
ка 125) позволило заполнить операндное поле по адресу 2013.
Тем временем были добавлены две новые ссылки вперед:
,WRREC (строка 65) и EXIT (строка 155). Вам следует про-
должить этот процесс до конца программы и самостоятельно
убедиться в том, что все ссылки вперед будут занесены пра-
вильно. Когда будет обнаружен конец программы, все элемен-
ты SYMTAB с признаком * будут указывать на неопределен-
ные имена, и, следовательно, ассемблер должен отметить их
как ошибки.
По достижению конца программы ассемблирование завер-
шается. Если не было ошибок, то ассемблер ищет в SYMTAB
значение имени, указанное в предложении END (в данном слу-
чае FIRST), и передает управление на данный адрес для испол-
нения ассемблированной программы.
В нашем примере мы использовали абсолютную программу,
так как для ассемблера типа загрузка — выполнение фактиче-
ский адрес загрузки должен быть известен во время ассемб-
лирования. Конечно, необязательно, чтобы адрес загрузки опре-
делялся программистом; он может назначаться и системой. Эю
не влияет на процесс ассемблирования, так как в любом случае
в счетчик размещений будет занесен фактический адрес начала
программы.
Однопросмотровые ассемблеры, результатом работы которых
является объектная программа, необходимы в системах, где
отсутствуют рабочие внешние запоминающие устройства для
хранения промежуточного файла между двумя просмотрами.
Такие ассемблеры также могут быть полезны, когда внешняя
память медленна или неудобна для использования по каким-
либо другим причинам. Работа однопросмотровых ассемблеров,
производящих объектные программы, несколько отличается от
описанной ранее. Как и прежде, ссылки вперед заносятся в
список. Однако теперь, когда будет встречено определение
имени, команды, ссылающиеся на это имя, могут уже отсут-
ствовать в оперативной памяти и, следовательно, будут недо-
ступны для модификации. В общем случае они будут уже за-
писаны на внешнее устройство как часть тела объектной про*
4 Зак, TJ2
граммы. Поэтому ассемблер должен сгенерировать другую
запись тела программы с соответствующим адресом команды,
а загрузчик занесет этот адрес в команду во время загрузки
программы.
Иллюстрация этого процесса дана на рис. 2.22. Вторая
запись тела программы содержит код, сгенерированный для
строк 10—40 исходной программы, изображенной на рис. 2.20.
Адреса операндов команд для строк 15, 30 и 35 сгенерированы
с нулевым значением. Когда в строке 45 встречается определе-
ние имени ENDFIL, ассемблер генерирует третью запись тела
ИСОРУ %001000ЛС0107А
Т.0 010 0 0.0 9.4 5 4 Г 4 6^0 0 0 0 0 3.0 0 0 0 0 0
T00200F15141009,480000.00100С281006 3000004 8000ОЗС2012
Л Л Л Л Л Л Л Л Л
ТлО0201Сл02д2024
Т002024190010000C100F001ООЗОС100С48000О081009,4 COOOOF1001 000
Л л л л л л л л л л л
ТОО2О13О22О30
ЛАЛ
!Г002031) IE04I00600I006E02039 3 02043D82039 281006300000 54900F2C203A3 82043
А ЛА Л Л Л Л Л Л Л Л Л
Х00205002205В
Л Л А
30 02 0 5 В 0 71010 0 С 4 С 0 0 0 0 0 5
А ЛА Л Л-
T0Q201F022062
Л АЛ
Т002031022062
Л АЛ
Т00206218041006Е02061302065509O0EDC20612C1O0C3820654C000O
Л АЛ Л Л Л Л Л Л Л
I.00200F
Рис. 2.22. Объектная программа, полученная из исходной программы на
рис. 2.20 с помощью однопросмотрового ассемблера.
программы. Эта запись определяет, что значение 2024 (адрес
ENDFIL) должно быть занесено по адресу 201С (адресное
поле операнда команды JEQ в строке 30). Таким образом, во
время загрузки программы величина 2024 заменит ранее за-
несенное значение 0000. Точно так же обрабатываются и дру-
гие ссылки вперед нашей программы. В результате^ для раз-
решения ссылок вперед, которые не могут быть обработаны
ассемблером, используются средства загрузчика. Конечно, при
передаче объектной программы загрузчику должен быть сохра-
нен первоначальный порядок ее записей.
В этом разделе мы рассмотрели только простые однопро-
смотровые ассемблеры для обработки абсолютных программ .
Мы предполагали, что в качестве операндов команд использу-
ются одиночные имена, а ассемблированные команды содержа!
фактические (не относительные) адреса операндов. Более ри-’*
витые средства ассемблера, такие как литералы, были заир'-
Ч Автор имеет в виду программы в абсолютных адресах. — Прим,
щены. Вам предлагается подумать о способах снятия некого
рых из этих ограничений (некоторые предложения можно пай
ти в упражнениях к данному разделу).
2.4.3. Многопросмотровые ассемблеры
При обсуждении директивы ассемблера EQU мы требовали
чтобы все имена в правой части (т. е. в выражении, задающем
значение нового имени) были предварительно определены в ис-
ходной программе. Аналогичные ограничения накладывались и
на директиву ассемблера ORG. В действительности такие огра-
ничения обычно накладываются на все директивы ассемблера,
которые (прямо или косвенно) определяют имена.
Причина этого кроется в самом процессе определения имен,
который используется в двухпросмотровом ассемблере, Рассмо-
трим следующую последовательность;
ALPHA EQU BETA
BETA EQU DELTA
DELTA EQU 1
Когда во время первого просмотра встретится метка ВЕТА, мы
не сможем назначить ей адрес, так как DELTA еще не опре-
делена. Поэтому мы не сможем вычислить значение метки
ALPHA во время второго просмотра. Это означает, что любой
ассемблер, выполняющий только два последовательных просмо-
тра исходной программы, не может обрабатывать такие после-
довательности определений.
Ограничения, связанные с запрещением ссылок вперед в
определениях имен, обычно не вызывают-у программиста серьез-
ных неудобств. В действительности подобные ссылки вперед
скорее порождают сложности у человека, читающего програм-
му, чем у ассемблера. Тем не менее некоторые ассемблеры
проектируются так, чтобы исключить необходимость таких огра-
ничений. Общее решение заключается в использовании много-
просмотрового ассемблера, который может сделать столько про-
смотров, сколько необходимо для выполнения процесса опреде-
ления имен. Совершенно необязательно, чтобы такой ассемб-
лер просматривал всю программу целиком более двух раз.
Вместо этого фрагменты программы, содержащие ссылки впе-
ред, запоминаются во время первого просмотра. Дополнитель-
ный просмотр таких запомненных определений делается по
мере продвижения процесса ассемблирования. По завершению
этого процесса выполняется обычный второй просмотр^
Существует несколько способов решения обрисованной выше
задачи. Метод, который мы опишем, заключается в запомина-
нии в таблице имен тех определений, которые содержат ссыл-
ки вперед. Для того чтобы облегчить вычисление значении
Гл, 2. Лесом б леры
1 HALFS2 E0U MAXLEN/2
2 MAXLEW EQU BUFEND-BUFfEft
3 TREVBT EQU BUFFER-1
4 BUFFER RESB 4096
5 BUFEND EQU *
б
О
2.4. Варианты построения ассемблеров
г
А
Рис. 2.23, Пример работы многопросмотрового ассемблера.
Г
Д
1 BUFEND 2034 0
HALFSZ 800 0
PREVBT 1033 0
MAXLEN 1000 0
BUFFER 1034
е
Рис. 2,23. Пример работы многоиросмотрового ассемблера.
а
имен, элементы данной таблицы содержат признак который
указывает на то, что данное имя зависит от значений nnvruv
имен. ян,‘"л
На рис. 2.23а показана последовательность предложении
определяющих имена, в которых используются ссылки вперед-
остальная часть исходной программы для нашего обсуждения
интереса не представляет и потому опущена. Последующие ча-
сти рис. 2.23 показывают, как могла бы выглядеть информа-
ция, занесенная в таблицу имен, после обработки каждого из
приведенных исходных предложений.
На рис. 2.236 приведены элементы таблицы имен подучив-
шиеся после первого просмотра предложения ’ J
HALFSZ EQU MAXLEN/2
Имя MAXLEN еще не определено, поэтому невозможно вычис-
лить значение HALFSZ. Вместо значения HALFSZ в таблице
имен запоминается определяющее его выражение. Элемент &1
показывает, что в определяющем выражении не определено
одно имя. Конечно, в реальной реализации это определение
может храниться где-нибудь в другом месте. SYMTAB может
просто содержать указатель на определяющее выражение, Имя
MAXLEN также занесено в таблицу имен и снабжено призна-
ком *, указывающим на то, что оно не определено. С этим
именем связан список имен, значения которых зависят от
MAXLEN; в данном случае HALFSZ. Обратите внимание на
схожесть со способом обработки ссылок вперед
смотровом ассемблере.
Аналогично обрабатывается определение
[(рис. 2.23в). В данном случае в состав определения
неопределенных имени: BUFEND и BUFFER. Оба
в однопро-
MAXLEN
входят два
этих имени
заносятся в SYMTAB вместе со списком, указывающим на за-
висимость MAXLEN от этих имен. Точно так же при обработке
определения PREVBT потребуется занесение этого имени в спи-
сок имен, зависящих от BUFFER (рис. 2.23г).
До сих пор мы просто запоминали определения имен для
последующей обработки. Определение BUFFER в строке 4
позволяет нам начать вычисление некоторых из них. Предпо-
ложим, что, когда мы читаем строку 4, счетчик размещении
содержит шестнадцатеричное значение 1034. Этот адрес запо-
минается в качестве значения BUFFER. Затем ассемолер пр
сматривает список имен, зависящих от значения BL1 -
Элемент таблицы имен для первого имени данного СППСч‘
(MAXLEN) показывает, что он зависит от двух имен, коь’рн^
к данному моменту не определены. Поэтому сразу вычисл >
значение MAXLEN нельзя. Вместо этого &2 заменяется на ‘
для того, чтобы показать, что теперь только одно *|МИ 1\°()1
делении (BUFEND) осталось неопределенным. Другое
2-5» При мери реп л иза и и 11
~-------------------------— -___ 1ПЗ
списка (PREVBT) можно вычислить так как пи«
ко от BUFFER. Выражение, опредеАяюще^'нХьшГрЖ'
рнс.“ “ 3аП0МННаеТСЯ в SYMTAB. Результат показГа^’
Дальнейшая обработка осуществляется аналогично Когда о
строке 5 определяется BUFEND, его значение заносится в таб
лицу имен. Список, связанный с BUFEND, предписывает ас
семблеру вычислить MAXLEN, а занесение значения MAXLFN
вызывает, в свою очередь, вычисление имен из связанного о
ним списка (HALFSZ). Как показано на рис. 2.23е, на этом
процесс определения имен заканчивается. Если какие-либо име
на остаются неопределенными, то они отмечаются как оши
бочные.
Процедура, которую мы только что описали, применяется к
именам, определяемым с помощью директив ассемблера типа
EQU. Вам следует подумать, как модифицировать этот метод
для того, чтобы он позволял обрабатывать ссылки вперед и в
предложениях ORG.
2.5. Примеры реализации
В предыдущих разделах мы обсудили многие самые общие
средства ассемблеров. Однако разнообразие машин и языков
ассемблера очень велико. В большинстве ассемблеров имеются
нестандартные средства, обусловленные структурой машины
или особенностями языка. В этом разделе будут рассмотрены
примеры трех ассемблеров реальных машин. Очевидно, что в
рамках одного раздела невозможно дать полного описания
какого-либо из этих ассемблеров. Вместо этого мы сфокусиру-
ем внимание на наиболее интересных или необычных средствах
каждого из них и выделим те аспекты конкретного проекта,
где базовые алгоритмы и структуры таблиц отличаются от
описанных ранее. _
Мы обсудим примеры ассемблеров для System/370, VAX и
CYBER. Прежде чем продолжить чтение данного раздела, вам
следует посмотреть в гл. 1 описания этих машин.
2.5.1. Ассемблер System/370
Относительная базовая адресация в System/370 ”сп°льзует
ся с той же целью, что и в УУМ/ДС,—для ч t т/370
занимаемого машинной командой. Полный адр У можно
занимает 24 разряда. Вместе с тем тот же " я
закодировать с помощью номера базового ре Р . п §у-
и смешения (12 разрядов). Однако есть и отличяе.^
:tcm/370 нет ни адресации относительно
чего-либо похожего на пасшипмшив
УУМ/ДС. Поэтому все команд" ссылаю,,1,,1‘““а"Д,ШП Ф°₽мат
память, должны использовать относительную бА опеРативнУ10
Ш1Ю. Как следствие этого при перемещении S’"0 адрсса-
граммы System/370 модификация требует™ тольиТ^ ПР°'
ментов данных, значениями которых являются *ак^ элс'
адреса (т. е. для адресных констант). Фактические
в S>pL'n’7370 •'"Обой регистр общего назначения (за пекли
чением R0) может использоваться в качестве базового X
ра. Решение о том, какие регистры использовать для этой цели
возлагается на программиста. В больших программах обычно
одновременно используются несколько различных базовых не
гистров. Какие регистры могут использоваться в качестве базе-
вых и каково их содержимое, программист сообщает при помо-
щи директивы ассемблера USING. По своим
хожа на директиву BASE языка ассемблера
Таким образом, предложения
функциям она по-
УУМ/ДС.
USING LENGTH,R1
USING BUFFER,R4
определяют в качестве базовых регистры R1 и R4. Предполага-
ется, что R1 будет содержать адрес LENGTH, a R4 — адрес
BUFFER. Так же как и в УУМ/ДС, программист должен
предусмотреть команды, обеспечивающие загрузку этих регист-
ров во время выполнения программы. Дополнительные предло-
жения USING можно помещать в любом месте программы.
Если базовый регистр в дальнейшем необходимо использовать
для других целей, то программист с помощью предложения
DROP может сообщить ассемблеру, что дальнейшее использо-
вание регистра в качестве базового запрещено.
Дополнительная гибкость в использовании регистров влечет
за собой увеличение объема работы, выполняемой ассемблером.
Для того чтобы знать, какие регистры общего назначения мо-
гут в данный момент использоваться в качестве базовых ре-
гистров и каково их значение, используется таблица Ьазовьа
регистров. При выполнении предложения USING в таолищ за-
носится новый элемент (или модифицируется уже ••
щий); при выполнении предложения DROP соот^тс - анд
элемент удаляется из таблицы. Для каждой K0N J О иЩСТ
которой является адресом оперативной памяти, < * Если
в таблице подходящий для адресации базовый р тся
для адресации подходит более одного рет истра, то >
тот, который дает наименьшую величину/мдш аНДЫ
один из регистров не подходит, то ассембл р у такой
невозможно. Процесс вычисления смещения
же, как и для УУМ/ДС.
Наряду с этим в языке ассемблера System/370 г
явное задание базового регистра и смещения непоСпеЭр^ено
исходном предложении. Например, в предложении р АСТВенио в
L R2,8(R4)
в качестве адреса операнда задан адрес смещенный in я
относительно адреса, содержащегося в R4. Такая форма аЛ7
сании может быть полезна, если известно, что некоторый пГ
гистр содержит начальный адрес таблицы или записи данных"
а программист хотел бы сослаться на определенную облает/
внутри этой таблицы или записи. При обработке команд в ко
торых явно заданы базовый регистр и смещение, ассемблер
просто заносит заданные значения в объектный код (в данном
случае базовый регистр R4 и смещение 8). Таблица базовых
регистров в этом случае не требуется; поэтому регистр, исполь-
зуемый подобным образом, не нужно описывать в предложении
USING.
Другой проблемой, которая возникает в ассемблере Sy-
stem/370, является выравнивание областей данных и команд
Некоторые команды выполняются более эффективно, если их
операнды выравнены по границам памяти, соответствующим их
длинам. Например, операнд длиной в одно слово (32 разряда)
должен начинаться с байта, адрес которого кратен 4, а операнд
длиной в полслова (16 разрядов) — с адреса, кратного 2. Точ-
но так же требуется, чтобы машинная команда начиналась с
байта, адрес которого кратен 2.
Заботу о таком выравнивании берет на себя ассемблер,
продвигая, если это необходимо, счетчик размещений. Предпо-
ложим, например, что счетчик размещений содержит 0015 и
необходимо разместить элемент данных длиной в одно слово.
В этом случае, прежде чем резервировать память для этого
слова, счетчик размещений следует увеличить до 0018 (ближай-
шее кратное 4 больше чем 0015). Байты объектной программы,
пропущенные для того, чтобы обеспечить соответствующее вы-
равнивание, называются пассивными байтами (slack bytes').
(В некоторых ассемблерах System/370 включение пли выклю-
чение выравнивания задается по выбору во время ассемолиро-
вания.)
Пассивные байты являются для объектной программы по1\
рянной памятью. Величина этих потерь существенно зависит о
того, в каком порядке определяются элементы дан - •
смотрим, например, последовательность предл / I Р
Рования памяти, изображенную на рис. 2.24а Еслпри^бр^
Сотке первого предложения счетчик Размсще”1 I
показано, адрес, кратный 4, то Р33мешения^с выра^
киванием потребуется 20 байт na^TIIo £ чт0 внесение
занимают только 14 байт, то это означает,
106
Адрес
Исходное предложение
0024 ©025 А PS с 1 БАЙТ
©028 ©02С ©02F 1г С ns PS F зс СЛОВО 3 БАЙТА <3 пассивных байта)
©030 0032 В US н ПОЛУСЛОВО (1 Пассивный байт)
0034 0038 • Е PS F слово (2 пассивних байта)
а
Адрес Исходное • предложение
• •
0024 0028 002С С02Е ©031 0032 В Е В С А DS BS DS PS PS F F Н зс с слово слово ПОЛУСЛОВО 3 БАЙТА 1 БАЙТ
Рис. 2.24. Влияние выравнивания данных на
памяти.
требуемый объем оперативной
памяти плиты и°В№₽ЧИЛ0 °$ъем занимаемой оперативной
тоебуюшир пт 3 50 °' Бсли сгРУПпировать элементы данных,
сокоатить ЧТ„Д 1НаКОВОГО ВЬ1Равнивания, то можно значительно
деления ляг™ НаКЛаДНЫе Расходы- Например, если те же опре-
не потпР£а;П°Л0ЖИТЬ В П0Рядке» показанном на рис. 2.246, то
не потребуется ни одного пассивного байта.
определенийРп^аЛ° ЧТ0 может сделать с последовательностью
мя оазмешрниРНпЫХ’ написанной программистом. В то же вре-
ролируется ассемблеппмЬНк,Х опеРандов непосредственно конт-
располагают ₽ ’ Большинство ассемблеров System/370
минимизиплпят1еМеИТЬ1 данных в литеральном пуле так, чтобы
1 ь потери памяти, Вначале назначаются адреса
2.5. Примеры реализации
_ . .., —_______________________________________^07
для всех литералов, которые требуют для своего размещения
двойное слово, затем — слово, полуслово и т. д.
' Ассемблер System/370 обеспечивает поддержку аппарата
управляющих секций (их называют CSECT). По своим функ-
пиям этот аппарат похож на средства, описанные в разд. 2.3.5.
то же время не предусмотрено никакого механизма, прямо
соответствующего программным блокам (см. разд. 2.3.4)
В System/370 управляющие секции могут состоять из несколь-
ких отдельных сегментов. Сборка этих сегментов осуществля-
ется ассемблером примерно так же, как это было описано для
программных блоков. Однако управляющие секции не образу-
ют единый программный модуль. Каждая из них остается са-
мостоятельной единицей и обрабатывается загрузчиком или ре-
дактором связей независимо от других секций.
д Для каждого внешнего имени, используемого в CSECT, про-
таммист должен зарезервировать одно слово для хранения
лоесной константы. Значение этой константы заносится загруз-
инком с помощью механизма, похожего на тот, что был описан
r пазд 2 3 5 Программист должен предусмотреть команды, ко-
сные обеспечат во время исполнения программы загрузку ад-
прсной константы в базовый регистр. Информация о том, какой
базовый регистр может быть использован для разрешения
внешних ссылок, сообщается ассемблеру с помощью предложе-
ИИЯпипп™™ожим ЧТО в одной из CSECT с помощью описанной
выше процедуры’ определен ба?ов™ ер“'Гб« "е-
метку, расположенную в другой CSECT Если тепе^ же ба-
чить совместную трансляцию ' ссылки из дру*
зовый регистр можно использование базового
гие метки этой внешней CSEC1. 1акое исно
регистра допустимо, поскольку ассемблер с0^Ра”я^
менты таблицы имен на протяжении всего пер л Д „
ты. Однако в этом случае будет утрачена возможность раздвль
ного ассемблирования этих управляющих се*11'1’ ПСПОЛЬЗует
Как можно видеть, язык ассемблера Sys tem/370 пепол
аппарат CSECT для достижения двух,ло1 ричн0 пр0.
целей — реорганизации объектной npoi ]р < программы иа от-
граммным блокам УУМ/ДС) и р_ м сеКциям УУМ/ДС).
дельные модули (аналогичнойУ"Рппогоаммисты, впервые позна-
Это часто приводит к тому, йт 1 1 подобной системе, пу-
комившиеся с данными концепциями на п д
тают эти два понятия. ппедоставляет также возмож-
Язык ассемблера System 370 предоста^ в„да,
кость использовать УпРавля‘.. 7еКцией (DSECT — Dunin } ",иие
которая называется фикти ПСПОЛЬзовано любое прел’ овятся
Tion . В DSECT может быть использ> ,ия не становятся
языка ассемблера, однако эти пред
slern/370 можно найти
частью объектной программы. Чаще всего DSFCT
Для описания структуры сложных областей да,L х Л3уеТС?
таблиц и т. п.), определенных вне данной программы3ам“Сеи’
использованные в DSECT, определяют имена ко™ui?
быть использованы для адресации полей записи или ' яа °ГуТ
(после того как будет задан подходящий базовый пД°ЛИЦ\Л
Дополнительную информацию о типовом ассемблере^'
в IBM [1979], IBM [1974] и IBM
|[1982].
2.5.2. Ассемблер ЭВМ VAX
В ЭВМ VAX используется намного более гибкий метол ко.
дирования операндов, чем в большинстве машин. Имеется не
обычно много способов адресации, и (за небольшим исключе-
нием) каждый из этих способов может быть использован в лю-
бой команде. Спецификаторы операндов, связанные с различ-
ными способами адресации, занимают различный объем памя-
ти. Как мы увидим, это увеличивает объем работы, выполняе-
мой ассемблером.
Терминология, используемая в языке ассемблера VAX, не-
сколько отличается от стандартного набора терминов, который
мы использовали. Например, есть два способа адресации, в
которых значения операнда хранятся как часть команды,— не-
посредственный и литеральный. (Для операндов этого типа мы
использовали в разд. 2.2 термин непосредственная адресация.)
Функционально эти два способа эквивалентны, и в исходной
программе они задаются с помощью одной и той же нотации.
Во время первого просмотра ассемблер, анализируя величину
операнда, решает, какой способ адресации использовать. Если
операнд является целым между 0 и 63 (или какой-либо другой
величиной, которую можно разместить в 6-разрядном поле),то
используется литеральный способ. Если операнд нельзя РазДД
стить в 6-разрядном поле или ассемблер еще не может опреде-
лить его значение, то выбирается непосредственный способ. [ и
непосредственном способе длина спецификатора операнда зави-
сит от типа операнда, используемого в команде (слово, длипыж
слово и т. д.). Длина спецификатора операнда для литера. |ык>
го способа всегда равна одному байту.
Обратите внимание, что операнды VAX, использующие •
ральный способ адресации, обрабатываются совершенно 11
чем литералы, о которых мы говорили в разд. 2.3. в ’ _
ассемблера VAX нет никаких средств, которые бы соотвс
вали тому, что мы называли литералами в нашем ассем
Имеется еще ряд случаев, когда длина спецификатора ею
ранда (а следовательно, и длина команды) должна опр >
ся ассемблером. Например, при использовании способа адпеса
цнн относительно счетчика команд поле смещения может ко-
дироваться как байт, слово или длинное слово. Ассемблер
выбирает длину этого поля в соответствии с величиной требуе-
мого смещения. Если в операнде команды какое-либо имя еще
не определено, то ассемблер во время первого просмотра не
может вычислить смещение. В этом случае выбирается смеще-
ние максимально возможного размера (длинное слово). Заме-
тим, что это решение нельзя отложить до второго просмотра,
так как длина команды влияет на значения всех меток, опре-
деленных в программе ниже данной команды.
Величина смещения для адресации относительно счетчика
команд вычисляется так, как это было описано в разд. 2.2.
Однако в момент вычисления целевого адреса во время испол-
нения программы счетчик команд будет содержать не адрес
следующей команды, а адрес следующего спецификатора опе-
ранда (если он есть). Это необходимо учитывать при вычис-
лении величины смещения.
В большинстве языков ассемблера длина ассемблированной
команды однозначно определяется по ее мнемоническому коду
операции. Для ЭВМ VAX это не так. Каждый спецификатор
операнда VAX в зависимости от типа операнда может иметь
длину от 1 до 9 байт. Например, в команде
MOVB RI, R5 ___ _______ ______
оба операнда находятся в регистрах. Каждый спецификатор
операнда требует 1 байт; поэтому ассемблированная команда
будет занимать 3 байт. В то же время в команде
MOVB 1,8 (R6)
для первого операнда используется литераль ь __ базовая
сацни (длина спецификатора 1 байт), а для для
относительная адресация. С учетом величинь $ 1 ким об-
спецификатора второго операнда ТР^У^ТСЯ аннмать 4 байт,
разом, вся ассемблированная команда буд
В команде
MOVB RI, ALPHA
для спецификатора первого операнда уР^^итсльно счетчн-
второго операнда используется адресе ешеиия его специфи-
ка команд. В зависимости от' “Образом, в зав,.-
катор может занимать от 2 до о • данная команда
самости от адреса, назначенного метке ALPHA, да,
может занимать от 4 до 7 байт. VAv должен во время
Это означает, что ассемблер Э i' ю болсе сложную
ПСрВОГО ПрОСМОТра ВЫПОЛНЯТЬ 31k
работу, чем, скажем, ассемблер System/370. Во время первого
просмотра ассемблер VAX должен анализировать не только
коды операции, но и операнды команд. Таблица кодов опеоа-
цпй также должна иметь более сложную структуоу так как п
ней необходимо иметь информацию о том, какие способы алпр
сации допустимы для каждого из операндов.
Язык ассемблера VAX обеспечивает возможность организа
ции управляющих секций, которые называются программными
секциями (PSECT — Program SECTions). Подобно CSECT
языка ассемблера System/370, PSECT используются для двух
различных целей — реорганизации программы и разбиения про-
граммы на модули. В языке ассемблера VAX обработка PSECT
отличается: меньшая часть работы выполняется ассемблером и
большая — программой связывания. Если из одной PSECT
происходит ссылка на имя, определенное в другой PSECT, и
эти секции ассемблируются совместно, то для ссылки исполь-
зуется адресация относительно счетчика команд. Так как вза-
имное расположение секций относительно друг друга во время
ассемблирования неизвестно, то величину смещения вычислить
нельзя. Поэтому ассемблер генерирует команды для программы
связывания, которые позволят ей определить смещение и за-
нести его в команду. Этот процесс похож на тот, что был опи-
сан в разд. 2.3.4 для разрешения ссылок между программными
блоками. Более детально мы рассмотрим работу программы
связывания в следующей главе.
При трансляции PSECT могут задаваться некоторые атри-
буты, в том числе атрибут доступа: «только чтение», «только
исполнение» и т. п. Кроме того, в каждой PSECT можно ука-
зать, разрешено или нет выравнивание элементов данных. ^Про-
блемы выравнивания в VAX похожи на те, что мы обсуж-
дали в связи с System/370.) Программа связывания собирает
вместе все сегменты каждой PSECT и все программные сек-
ции, имеющие аналогичные атрибуты. Средства операционной
системы VAX могут быть использованы для обеспечения защи-
ты PSECT в соответствии с ее атрибутами.
Ассемблер VAX предполагает по умолчанию, что все имена,
которые были использованы, но не были определены во время
ассемблирования, являются внешними ссылками. Никакого яв-
ного объявления внешних имен (подобно предложению EXi-
REF УУМ/ДС) не требуется. К несчастью, это приводит к >
му, что ошибки типа пропуска символа в имени нельзя оона-
ружить до момента связывания программы. Однако програм-
мист может задать режим работы ассемблера, который отменя-
ет данное правило умолчания и требует явного объявления
внешних имен.
Дополнительную информацию об ассемблере VAX мож" '
цайти в DEC [1982] и DEC [1979],
Ш
2.5.3. Ассемблер ЭВМ CYBER
Язык ассемблера ЭВМ CYBER кптпп:,-
PASS, имеет несколько существенных о!л .',„пааь"!ается Со"-
кон. Первое отличие является прямым следствием^/™’
машины. Дело в том. что размер машинного слова Л^оУри
зволяет разместить в нем несколько различим? ^jBER по-
„ых команд. В общем случае зада^Г
упаковка как можно большего кочнчрстпя р является
положенных команд в одно слово объектнойпронщммы к"
вечно, можно было бы просто размещать по пХ/Р Ко’
команде в слове, а неиспользованное пространство ^ПШИННОЙ
невыполняемыми командами, но такое neiuLJl заполнять
^^=.гння - Тт.;
вЭт“Гк
число 60 (число разрядов слова CYBER). При генерации
команды количество разрядов, требуемое для ее размещения
вычитается из счетчика позиций. Если в текущем сло^е Z
места для размещения очередной команды, то оставшиеся раз-
Р пЯСбп °Н? еСТЬ заполняются неисполняемыми командами
*ДД Р 6 беРется новое слово Объектной программы. В этот
еТЧИК Размещенин 11 счетчик слов (его мы опишем в
этом разделе ниже) увеличиваются на 1, после чего они будут
содержать адрес следующего слова. „лычяю после-
Предыдущее описание представляет сооои обычно пос
дователыюсть действий: команды (1’;’”n^eMne"Ja эт0 возможно,
ковываются в машинное слово до J ’ слову. Однако
а затем осуществляется переход к сло; У ГпеиуЮщему слову
в некоторых случаях требуется пеРея достаточно места для
несмотря на то, что в текущем слов г_ 0 кода. Такая не-
размещения следующего элемента о CYBER примени-
обходимость является следствием то: , ппеоативной памяти,
ется пословная, а не побайтная адрс ~ 0ВП0Г0 перехода. Ад-
Рассмотрим, например, команду У быть адресом слова.
рее операнда в данной комавд^ Дбудет занесен адрес, задан-
После того как в счетчик кома д. У aHAOftf выбираемой
ный в команде перехода, след) упакованная в слово с
лля выполнения, будет первая команда^уп перехода. Это озна-
адресом, равным целевому адре У 4 дать управление то. ’
чает, что мы можем непосредств е слова объектной Щ
ко на команду, расположенную в начале
> рам мы.
Процесс размещения команды или элемРНтЯ
чале слова, даже если в предыдущем слово пп данных в на-
мазывается проталкиванием (forsing upper) Пп,?^04"0 МССта’
предыдущего слова заполняется неисполняемымиостаток
счетчик слов и счетчик размещений увеличиваются 1яа"Дами’
счетчик позиций заносится число 60. Ассемблер СОМРАЧЧ * “
полияет проталкивание в следующих случаях: ВЬ1'
1. Ассемблируемое предложение имеет метку (так как а-т
рсс метки указывает на начало слова). Д*
2. Ассемблируемое предложение является предложением ое-
зервироваиия памяти, и в нем не задана упаковка битовых по-
3. Предыдущее предложение является предложением безус-
ловного перехода (в этом случае единственный способ выпол-
нить следующую команду — передать на нее управление).
Программист может задать проталкивание для любого предло-
жения, задав в поле метки символ -ф. Для того чтобы отменить
автоматическое проталкивание, достаточно задать в поле мет-
ки символ —.
Кроме счетчика позиций ассемблер использует в своей ра-
боте еще два счетчика — счетчик размещений и счетчик слов.
Вместе эти два счетчика служат для того же, что и LOCCTR,
описанный в разд. 2.1. Основная функция счетчика слов та же,
что и у LOCCTR: счетчик слов вместе со счетчиком позиций
указывает на относительное местоположение в объектном коде
следующей ассемблируемой команды. Счетчик размещений ис-
пользуется ассемблером для назначения адресов внутренним
меткам программы. Ранее для этого мы также использовали
LOCCTR.
Обычно значения счетчика слов и счетчика размещении со-
впадают. Однако, если это необходимо, программист moaci
помощью директив ассемблера изменить значение счетчика раз
мещений. Это может оказаться полезным только в весьма ни
цифической ситуации когда при ассемблировании ооъекпл-И'
код размещается в одном месте, а перед исполнением дол/ у
быть перемещен в другое. В этом случае программист щ-мсуу
значение счетчика размещений так, чтобы оно соответство у
адресу расположения объектного кода на момент испол с
На рис. 2.25 показан пример такого использования су
размещений. Данная программа содержит большой уф |>
пользусмый во время ее исполнения для ввода и выводу
грамма состоит из трех различных разделов, которые в > $
ются при вызове программы. Однако только один и'3 [|1ИС.
разделов используется при исполнении программы. с -
мые команды для каждого из трех разделов *1Редстав’,« ..’0Д1
исходной программе в виде отдельных частей. Объектив
ИЗ
полученный в результате тпямлпп, "
занимает значительный объем оперативнп“КДОЙ И3 Этих частей
Если бы объектная поогтмм-?« В памяти. й’
фером и тремя разделами, то она £отпебоУЖеНа ВМесте с бУ-
объема памяти. Для экономии места шГмп а бы большого
ся приемом показанным на рис 2 восп°льзовать.
Раздела 1 (наибольший раздел) асс™£п„ Объектный код для
обычным образом. В то
дела 3 загружается в область буфепа ЧтЯ Д д а 2 и Ра-
зуется до тех пор, пока не начнется ввод поэтомТпрп6 ИСП0ль’
нос размещение команд в этой области’ппД У ПсРВ011а1’аль-
Если для выполнения будет выбраГр'азХ’ 2 ",™зь,ва<=1-
ТО соответствующий раздел объектного кола б™Л Р яел 3'
программой из области буфера на место кот» £е|’емещс'1
(рис. 2.256). Теперь требуемый раздел выбирается просто3»,,'
зовом объектного кода, а буфер может использовать"? для „Д'
да данных. дли вв°ш
Программист должен быть уверен, что при таком перемете,
нии объектного кода метки будут определены правильно Рас
смотрим, например, команду с меткой SKIP2 на рис ' 2 25в
(строка 11). Поскольку счетчик слов был переустановлен
(строка 7), то код Разделов 2 и 3 будет расположен внутри
буфера. Если бы программа ассемблировалась обычным обра-
зом, то в этом случае значением метки SKIP2 был бы адрес
внутри буферной области. Однако фактически во время испол-
нения команды этого раздела будут расположены в памяти,
общей для всех трех разделов. Поэтому целевой адрес в коман-
де перехода в строке 10 должен быть адресом в этой области,
а не в области буфера.
Эта проблема решается с помощью задания в качестве но-
вого значения счетчика размещений начального адреса буфер-
ной области. Напомним, что в данном ассемблере для присваи-
вания меткам значений используется счетчик размещении, а не
счетчик слов. Поэтому метке SK1P2 будет присвоено оиачсиие,
соответствующее адресу, по которому она оудст РД^’о-’
во время исполнения, а не адресу на момент 1 как все*
Аналогично обрабатывается код Раздела 3- ‘ ое значенпе
три раздела будут оттранслированы, п^° ю предложения
счетчика слов восстанавливается с .,станаВливает зна-
0RG в строке 18. Предложение в СТР Д ию счетчика слов, и
Чение счетчика размещений Рав«Хпе^Тол>кещ , '
Обычный процесс ассемблирован!! у ммные блоки (их паз
ь В COMPASS предусмотрены
Вак)т подпрограммными блокам1\ппогоаммами — siibprogi' в
Янющие секции (их называют Р процессом, оп11^а‘ а10Тся
обработка в основном сх * все литералы раз*
^'14Д. 2.3, за исключением того,
Ill
Рис. 2.25. Перемещение объектного кода во время исполнения программы
о каждой подпрограмме отдельным блоком. Для каждого под-
программного блока ассемблер заводит отдельный набор счет-
чиков (слов, размещений и позиций).
Последнее необычное свойство COMPASS, которое мы об-
судим, заключено в самом языке ассемблера. Для большинства
ЭВМ код машинной операции однозначно определяется мнемо-
ническим кодом исходного предложения. Для CYBER это не
так. Рассмотрим предложения
SAI А2
SAI В2 4-ТАВ
SAI Х1 + В1
SAI XI —В1
Первое из них будет ассемблировано в 15-разрядпую коман .
с машинным кодом операции 54; второе — в 30-разряднуо
команду с кодом операции 51; третье — в 15-разрядную коман-
ду с кодом операции 53; четвертое недопустимо. _ ,
При интерпретации мнемонических кодов, подобных S.\i
большинства других кодов языка ассемблера CYBER), неоо.м •
димо анализировать операнды. Подобные команды исх
программы известны как синтаксически определяемые
поскольку они распознаются по своему синтаксису (т. е. '!
ме предложения). Ассемблер COMPASS обрабатывав, 11
команды, просматривая мнемонический код операции и on/' "иС
ды и извлекая символьную строку, описывающую син<т‘!‘'1'1С.
Для третьего из рассмотренных выше предложений синтак
ский дескриптор будет иметь вид SAX-f-B. Этот ^ескр ' ;1
определяет команду группы А, операндом которой яв. 1
2
0РГ1
SAI
I
Строка
1
Исходное предложение
IDENT
3
5
6
7
8
9
ZR
B4.SKIP1
SKIF1
BUFFER
0FT2
SA6
EQ
DSS
ORG
LOC
SA2
1000
BUFFER
ОРТ1
10
NZ
B3,SKIP2
сумма
11
12
13
14
15
16
17
18
19
20
SKIP2
OF73
SKIP3
SA7
EQ
LOC
SA6
0PT1
EQ
SA6
EQ
QRG
Lt)C
END
регистров X и В.
подполей, которые могут
PIZTI'W'—-
B1,B3,SKIP3
BUFFER+1000
*0
в
Рис. 2.25в.
Существуют 22
к°д раздела 1
ВЫХОД
БУФЕР ДЛИНОЙ 1000 СЛОВ
КОД РАЗДЕЛА 2
выход
КОД РАЗДЕЛА 3
ВЫХОД
••«диилеи клтппкго различных дескриптора
синтаксических дескр°ГптороГ ₽ОВа1ЬСЯ ДЛЯ полутеяия таких
кодов 'о аяспче^ки определяемые команды хранятся в таблице
скрипт псРаци** в соответствии со своими синтаксическими де-
хРйццГ°РаМИ' АЛЯ каждого элемента в таблице дополнительно
исхо I ТСЯ инФ°Рмацпя» определяющая, как различные части
Гр JДИог° предложения должны размещаться в объектной про-
ЛепММе' обРаботке предложений исходного языка ассемб-
P вначале ищет в таблице кодов операций мнемонический
код команды. Для некоторых команд такой поиск оказывается
успешным. Однако для синтаксически определяемых команд,
таких как SA1, он оканчивается безрезультатно. В этом случае
ассемблер просматривает исходное предложение и извлекает из
него (как было описано ранее) синтаксический дескриптор. За-
тем выполняется второй просмотр таблицы. Если и этот поиск
закапчивается неудачей, то опознание команды невозможно.
Дополнительную информацию об ассемблере CYBER можно
найти в CDC (1982а].
Упражнения
Раздел 2.1
1. Воспользуйтесь алгоритмом, приведенным
программы на рис. 2.1. Полученный вами результа? лпл^ Д‘гЯ НСХ0Д1'01’
как показано на рис. 2.2 и 2.3. р зультат должен быть таким,
2. Воспользуйтесь алгоритмом, приведенным на пип 9 t
щей программы УУМ: р поденным на рис. 2.4, для следую-
SUM START 4000
FIRST LDX ZERO
LDA ZERO
LOOP ADD TABLE,X
TIX COUNT
JLT LOOP
STA TOTAL
RSUB
TABLE RESW 2000
COUNT RESW 1
ZERO WORD 0
TOTAL RESW 1
END FIRST
пиг 9 иотые'1ал°сь, для некоторых операций в алгоритме на
гКч>гятАпп еуда|1° Детального описания. (Например, операция поиска моди-
В П0Ле 0Г1сРаиД°в-) Перечислите все, какие только можете,
зорят! Роваиные операции и подумайте, как можно было бы их рса.пь
4. Алгоритм иа пис 9 d
время инженерный подход к в виде единого блока. В то же,
чтобы большие программы оачГшпя^иию ’’Рограммного обеспечения требу. ,
Деленными интерфейсами ПпртЛаЛИСЬ н<2 несколь,<о модулей с четко оирс-
алгоритма. Укажите функции набоР модулей для реализации эт.и >
7мСНогиеЬЗУеТСЯ ДРУГН”И частямиГасс?мбМлОеДраЛеЙ “ °ЯЙШНТе’
^1еткн Должны начинаться ИнПСппп3^ЮТ сво^°дный формат записи комант
ПОдя («ОД onepaj-.ип опеп?плмСТ°ЛбЦе нсходного предложения, '
^бом столбце. Друг от „D’vr .P.JАЫ' комментарии) могут начинаться 1
м’-ннть алгоритм нашего "ассемблер отДеляются пробелами. Как надо ю
в свободном формате* ассемблера для того, чтобы он смог работа и-
6. Алгоритм на рис. 2 4 позволяет » " —-----И?
ХОДНОА программе. Однако существует Х™ НСК0Т0Рые из ошибок „
гут возникать в процессе ассемблирован я ° других ошибок, котовый ИС"
каждая из этих ошибок может быть об. аружеР°аГР^’м УУМ- КогдаР а
при этом предпринять ассемблер? РУжена н какие действия должен
раздел 2.2
1. Может ли ассемблер самостоятельно решить
па быть сгенерирована в расширенном формате? Это" И3 Комаид ^лж-
программиста заботу о явном указании таких команд позволит снять с
ка +•) ---- ‘д с помощью призиа*
2. Как мы уже говорили, предложение BASE сл^.т „
дачи информации ассемблеру. Программист должен кппма ^"Шь ДДя пере-
рсть команды наподобие LDB для загрузки слптпЛп ’ предусмот-
в базовый регистр. Может ли
ду LOB по директиве BASE? Если да, то в “£ " ™!Р"|’ОМТЬ км,а|"
минусы подобной интерпретации предложения BASE? «ются плюсы и
„Рот^мТуЖс: °бЪеКТ"ЫЙ КОД W ««
SUM START 0
FIRST LDX #0
LDA #0
4- LDB #TABLE2
BASE TABLE2
LOOP ADD TABLE,X
ADD TABLE2.X
TIX COUNT
JLT LOOP
4- STA TOTAL
RSUB
COUNT RESW 1
TABLE RESW 2000
TABLE2 RESW 2000
TOTAL RESW 1
END FIRST
4. Сгенерируйте закопченную объектную программу для исходной про-
граммы из упр. 3.
5. Модифицируйте алгоритм, показанный на рис. 2.4, так> тгчтой^
обрабатывал все допустимые в УУМ/ДС способы адРеса^"’;ьной °Р
зятся эти изменения на предложенной вами в упр. 2.1.4 ду
туре?
чтобы ОЯ
изменения
6. Модифицируйте алгоритм, показанный на р • этц
позволял получать перемещаемые программы. К
“а предложенной вами в упр. 2.1.4 модульной стру УР программ
7. Формат записи-модификатора *орощс’ "°да°ДИиТ данных распола-
У-УМ/ДС потому, что все адресные поля в была бы выглядеть
Га<отся, начиная с границы полубайта. Как д _ еслн бы адреСные
запись-модификатор, если бы это было ь ‘ внутрн байта и могли бы
поля мо.ли бы начинаться с произвольного места вну 1
имен* произвольную длину)?
8. Предположим, что мы сделали программу на рис. 2.1 перемещаемой.
Эта программа написана для стандартной модели УУМ, поэтому все адреса
' операндов являются фактическими адресами и имеется только один команд-
ный формат. Во время ее загрузки практически каждая команда объектной
программы нуждается в модификации адресов операндов. Это потребует
большого количества записей-модификаторов (что более чем в два раза
увеличит размер объектной программы). Как можно было бы включить
информацию, необходимую для перемещения программы, без столь значи-
тельного увеличения размера объектной программы?
Раздел 2.3
1. Модифицируйте алгоритм, показанный на рис. 2.4, так, чтобы
мог обрабатывать литералы.
2. Можно ли было в программе, приведенной на рис. 2.9, в строках
и 145 использовать литералы? Почему мы в этом случае не стали их
пользовать?
он
135
ис-
3. Немного расширив нашу литеральную нотацию, мы могли бы запи-
сать команду в строке 55 рис. 2.9 в виде и
LDA =W'3'
указав, что литеральный операнд является словом и имеет значение ван-
ное 3. Хорошо ли это? ’ 1
4. Непосредственные операнды и литералы — это два способа задания
значения операнда непосредственно в исходном предложении. Каковы пре-
имущества и недостатки каждого из них? В каких случаях один предпо-
чтительнее другого?
5. Предположим, что мы внесли следующие изменения в программу на
рис. 2.9:
а) Исключили предложение LTORG в строке 93.
б) Заменили предложение в строке 45 на 4* LDA ....
в) Заменили операнды в строках 135 и 145 на литералы (и исклю-
чили строку 185).
Каким будет в этом случае объектный код для строк 45, 135, 145, 215
и 230? Как будет в этом случае выглядеть литеральный пул? Замечание:
для выполнения этой работы полная перетрансляция программы не тре-
буется.
6. Предположим, что имена ALPHA и ВЕТА являются метками исход-
ной программы. Объясните, чем различаются две следующие последоватедь-
ности предложений:
a) LDA ALPHA —ВЕТА
б) LDA ALPHA
SUB BETA
7. Чем различаются нижеприведенные последовательности предложении.
a) LDA #3
б) THREE EQU 3
LDA
в) THREE EQU
LDA
#THREE
3
THREE
я Модифицируйте алгоритм, показанный на рис. 2.4, так, чтобы он
мог работать с несколькими программными блоками.
о Модифицируйте алгоритм, показанный на рис. 2.4, так, чтобы он
мог работать с несколькими управляющими секциями.
10 Предположим, что в ассемблере реализованы все возможности, опи-
, н разд. 2.3. Как следует в этом случае изменить таблицу имен по
сравнению с тем, как она описана в разд. 2.1?
11 Если различные управляющие секции ассемблируются совместно, то
лпые ссылки между ними могут быть обработаны ассемблером (вме-
”^°того чтобы оставлять их загрузчику). Например, в программе, приве-
сто того 2 15 выражение в строке 190 может быть вычислено непо-
деннои на I так как его таблица имен содержит всю пеоб-
Жимую информацию. В чем заключаются преимущества и недостатки
узкой обработки?
12 Пусть в программе, приведенной на рис. 2.11, мы использовали
я поогоаммных блока — непоименованный блок и CBLKS. Пред-
только ДВ ‘ дЛрменты данных CDATA включены в непоименованный блок,
положим, что а сделать изменения в исходной программе? Покажите,
КаКИя в’этомСлучае будет получена объектная программа.
КЭКа.ч Поедположим, что метка LENGTH определена так, как в про-
показанной на рис. 2.9. Чем различаются две нижеследующие по.
ддедовательности предложений?
a) LDA LENGTH
SUB #1
б) LDA LENGTH-I
14. В соответствии с
ния, тип и интуитивный
выражений:
определениями имен на ряс. 2.10 укажите значе*
— /------- — для каждого из следующих
смысл (если он есть)
a) BUFFER —FIRST
б) BUFFER + 4095
в) MAXLEN - 1
г) BUFFER 4- MAXLEN - 1
д) BUFFER-MAXLEN
е) 2* LENGTH
ж) 2* MAXLEN — I
з) MAXLEN - BUFFER
и) FIRST + BUFFER
к) FIRST — BUFFER + BUFEND
15. В программе, приведенной на рис. 2.9,
MAXLEN EQU BUFEND — BUFFER
Нем это лучше записи вида
MAXLEN EQU 4096
... Можно ЯН В ПРВвеДе
•У 190 на rwicpFR
MAXLEN EQU DUFEND-
строка 107 записана как
на ряс. *15> м“е““1Ь С1₽°
а строку 133 на
4- LDT
# MAXLEN
как мы это сделали на рис. 2.9?
17. Ассемблер
нс определенные
ссылками. В этом
Хорошо ли это?
мог бы просто предполагать, что все ссылки
в данной управляющей секции, являются
случае отпадает необходимость в предложении
на имена,
внешними
EXTREF.
18. Каким
обойтись без
достатки?
образом ассемблер, допускающий
предложения Г”------
EXTDEF? Какие здесь
внешние ссылки, мог бы
есть преимущества и йо-
,9:ЛССемблеР мог бы автоматически использовать расширенный формат
которых используются внешние ссылки. В этом
В чем заключаются преимущества .^недостатки тХвдода? "РИЗНаК +'
для команд, в операндах
случае программист мог
20. В некоторых системах управляющие секции могут быть скомпонп
ваны из нескольких частей точно так же, как программные блоки KaS
—отп Перед ассемблером? Как они могут быть разрешены?
проблемы ставит это
21. Предположим,
казано на рис. 2.15.
RDREC—COPY
что имена RDREC и COPY определены так, как по
В соответствии с нашими правилами выражение
является недопустимым (т. е. ассемблер и/или загрузчик откажутся его
обрабатывать). Предположим, что в силу каких-либо причин программе
действительно необходимо значение этого выражения. Как это можно сде-
лать, не меняя правил составления выражений?
22. Мы рассмотрели большое количество директив ассемблера, и еще
многие другие директивы могли бы быть реализованы в реальных ассембле-
рах. Их поиск путем последовательного сравнения может оказаться весьма
неэффективным. Как мы могли бы использовать таблицу, например похожую
на ОРТАВ, для того, чтобы ускорить распознавание и обработку директив
ассемблера? (Указание: ответ может зависеть от языка, на котором написан
ассемблер.)
23. Что кроме листинга исходной программы со сгенерированным объем-
ным кодом могло бы быть полезно для программиста? Предложите не-
сколько вариантов листингов, которые могут быть сгенерированы, и р.
смотрите структуры данных или алгоритмы, необходимые для их построению
Раздел 2.4
1. Рассмотрите базовый ассемблер, алгоритм которого показан
рис. 2.4. Какие таблицы и подпрограммы следует включить в корневой
мент этого ассемблера?
на
сег-
2. Какие таблицы и подпрограммы следует включить в корневой ю
мент усовершенствованного ассемблера, в котором реализованы воз •
сти, описанные в разд. 2.3?
3. Процесс разрешения нескольких ссылок вперед должен трсо' ж .
меныпих накладных расходов, чем полный второй просмотр ,|5'х0'^ . е 1Ч
граммы. Почему же для повышения эффективности все ассемблер
пользуют однопросмотровую схему ассемблирования?
4. Предположим, мы хотели бы, чтобы наш ассемблер выдавал
перекрестных ссылок для всех имен, использованных в исходной пр > •
Для программы, приведенной на рис, f2.5, такой листинг мог бы
дующий вид:
Упражнения
Имя Строка определения Строка использования
COPY 5 ——>
FIRST 10 255
CLOOP 15 40
ENDFIL 45 30
EOF 80 45
RETADR 95 10, 70
LENGTH 100 12, 13, 20, 60, 175, 212
Как ассемблер может это сделать? Укажите шмаиршш
буется при этом внести в алгоритм и таблицы, описав'^
5. Может ли однопросмотровый ассемблер создавать п,™
объектную программу и обрабатывать внешние ссылки? Опи...^Р “5аемую
„ля этого алгоритмы обработки и укажите иотеХлышо “уд,^™УеМЫС
6. Как можно в однопросмотровом ассемблере реализовать литералы’
7. Мы рассмотрели однопросмотровые ассемблеры, в которых опеп™
дэми команд могут быть только одиночные имена. Как сделать к
однопросмотровыи ассемблер мог обрабатывать команды вида ‘ ’ * 5 6 7 8 9 10
JEQ ENDFIL 4-3
где имя ENDFIL еще не определено?
8. Опишите алгоритм простого однопросмотрового ассемблера, работаю-
щего по схеме загрузка — выполнение.
9. Предположим, что команда, в которой используется ссылка вперед,
должна ассемблироваться с помощью адресации относительно счетчика
команд. Как можно ее обрабатывать с помощью однопросмотрового ас-
семблера?
10. Процесс разрешения ссылок вперед в однопросмотровом ассемблере,
создающем объектную программу, весьма похож на процесс связывания,
описанный в разд. 2.3.5. Почему мы нс ограничились простым использова-
нием записей-модификаторов для разрешения ссылок вперед?
Н. Как можно расширить метод, описанный в разд. 2.4.3, для обработки
ссылок вперед в предложениях ORG?
Глава 3. Загрузчики и программы
связывания
рова^нньге ^«ш'анды н6?н:™„а1%ПРд°а?наь“а,.оСОда₽1К"Т 0ТТра"“"
ио,-, программы, и, кроме то™ опредёлке пе""Ые "3 ИСХ°А-
иой памяти, куда эти команды и данные должны о °Пера™в'
В гл. 2 мы познакомились с тремя следующим,! процТсХ^’'
1. Загрузкой, обеспечивающей размещение поогоаммы »
оперативной памяти для исполнения/ Р Р мм в
2. Перемещением, которое позволяет модифицировать обл.
ектную программу так, что она может загружаться с адреса
отличного от первоначально заданного (см. разд. 2.2 2) 1
3. Связыванием, обеспечивающим объединение двух или бо-
лее раздельно оттранслированных объектных программ и пре-
доставляющим информацию, необходимую для разрешения ссы-
лок между ними (см, разд. 2.3.5) .
Загрузчик — это системная программа, выполняющая за-
грузку. Многие загрузчики обеспечивают, кроме того, переме-
щение и связывание. В некоторых системах функция связыва-
ния отделена от функций перемещения и загрузки. Связывание
выполняется специальной программой связывания (или редак-
тором связей), перемещение и загрузка — загрузчиком. В боль-
шинстве случаев трансляторы (т. е. ассемблеры и компилято-
ры) создают в каждой конкретной системе объектный код в
некотором стандартном формате. Таким образом, загрузчик и
программа связывания могут использоваться вне зависимости
от того, на каком языке была написана исходная программа.
В этой главе мы изучим вопросы проектирования и реализа-
ции загрузчиков и программ связывания. Для простоты мы ча-
сто будем использовать термин «загрузчик» вместо «загрузчик
и/или программа связывания». Ввиду того что процессы ас-
семблирования и загрузки тесно связаны, данная глава по сво-
ей структуре похожа на предыдущую. Многие из примеров, &
пользованных нами при изучении ассемблеров, появятся
этой главе. Во время обсуждения ассемблеров мы рассмотр
некоторые свойства и возможности, которые касаются ,ча1' ‘я
семблера, так и загрузчика. В этой главе мы вновь встрет
с такими концепциями. Естественно, что теперь нас в осн° гь
будут интересовать функции загрузчика, однако важно п0‘
о тесной связи между трансляцией и загрузкой npoip^ •
Как и в предыдущей главе, мы вначале рассмотрим основ-
функцию изучаемого программного обеспечения — в дан-
случае загрузку объектной программы в оперативную па-
П°ть для последующего ее исполнения. В разд. 3.1 представлен
^Гголютный загрузчик, (absolute loader). Подобный загрузчик
уог бы использоваться для УУМ. совместно с ассемблером,
описанным в разд. 2.1.
В разд. 3.2 разбираются вопросы перемещения и связывания
программ с точки зрения загрузчика. Мы обсудим несколько
возможных способов представления объектной программы и ис-
следуем, как они связаны со структурой ЭВМ. Мы также рас-
смотрим связывающий загрузчик (linking loader), представляю-
щий собой наиболее совершенный тип загрузчика, который ис-
пользуется в большинстве современных вычислительных систем.
В разд. 3.3 приведены некоторые из наиболее часто встречаю-
щихся свойств загрузчика, которые не имеют прямой связи со
структурой машины. Как и прежде, нашей целью является не
рассмотрение всех возможных свойств, а изучение концепций и
технических приемов, наиболее часто применяемых при созда-
нии загрузчиков.
В разд. 3.4 обсуждаются возможные альтернативные спосо-
бы реализации функций загрузчика. Мы разберем различные
способы выполнения перемещения и связывания, а также пре-
имущества и недостатки каждого из них. С этой точки зрения
будут рассмотрены редакторы связей (выполняющие связыва-
ние до загрузки) и схема динамического связывания (в кото-
рой связывание откладывается до момента исполнения про-
граммы).
л Наконец, в разд. 3.5 мы вкратце обсудим некоторые приме-
ры реальных загрузчиков и программ связывания. Мы рассмо-
трим те же машины, для которых в разд. 2.5 были описаны
ассемблеры, и укажем на взаимосвязь, существующею меж. у
ассемблером и загрузчиком. Как и ранее, мы с^Рел ‘
наше внимание на тех аспектах системных компон , 4
зависят от особенностей аппаратуры или програ
Чения.
3.1. Основные функции заг₽У" фу11КЦ„„
В данном разделе““сопрограммы в“"“Опспомсн''’-
загрузчика — запись об адРес начала функ-
мять и передачу УпРавл^с теМ, как вЫПОЛ”я‘°о11Кой для'по-
Вероятно, вы уже знаком служИТЬ отправно*^ загрузчика»
Нии. Данный раздел буд б сложных ФУ <оТОрый может
^дующего обсуждения более загрузчик, кот 1
Здесь мы рассмотрим аосол
быть использован совместно с ассемблером, описанным в
разд. 2.1. Для представления объектной программы будет ис-
пользоваться формат, описанный в разд. 2.1.1. Пример объект-
ной программы показан на рис. 3.1а.
ИдСОРТ дОО 1 ОООООО IО 7 А
^ооюоо^ЕдИюзЗдАвгоз^ооюзбдгвюзОдЗоюПдйвгоЫдЗсюоЗдОоюгА^сюз^ооюгв
^0010 1 Ед1 ^ОС 103648206 1д08 ЮЗЗдбСООООА 54 ГАбдОООООЗдОООООО
ТдОО2О39д1ЕдО4 ЮЗОдОО 1030aE020 5Da302031aU8205Da28 10 30a302057a54 90392C205E382Q3S
ТОО2О571С1 0103 6 4C0000F 100 100004 1Q3OE0Z0 7 930 20 6 4,5Q9039DCZ0792С1UJ6
ТО 0 2 0 7 3 О 7 3 6 2 0 6 4 4 С О О О О О 5
Л АЛ Л Л
^OQIOOO
Адрес________________Содержимое
оооо 0010 ♦ • • OFFO » хххххххх хххххххх о • о хххххххх хххххххх хххххххх • • • хххххххх хххххххх хххххххх • • • хххххххх хххххххх. хххххххх • • • хххххххх
1000 14103348 20390010 36281030 301015481
1010 20613С10 0300102А 0С103900 102 DOC 10|
1020 36482061 0810334С 0000454F 46000003
3030 ООООООхх хххххххх хххххххх хххххххх ^”COPY
• • • • •
• • • • •
• • • • •
2030 хххххххх хххххххх хх041030 001030Е0
2040 205D3020 3FD8205D 28103030 20575490
2050 392С2О5Е 38203F10 10364С00 00F10010
2060 00041030 Е0207930 20645090 39DC2O79
2070 2С103638 20644С00 0005|хххх хххххххх
2080 хххххххх хххххххх хххххххх хххххххх
• • • • •
• • • •
• • • • *
6
Рис, 3.L Загрузка абсолютной программы.
Поскольку от нашего загрузчика не
- — — « ~ ~ Г
связывания и пеоемегпЛ загРУзчика не требуется выполнения
ста. Все выполняет^ НИЯ пРогРамм> его работа весьма про-
чтобы удостовепптг г ЗЭ один просмотр. Вначале, для того
ки, корректна /и и/’ ЧТ° пРогРамма’ переданная для загруз-;
памяти) ппосмйтпг ° ДЛЯ Нее достаточно места в оперативной
тельно считываются ваетси запись-заголовок. Затем последов.i-
них объектный кип записи тела программы и содержащийся в
данному адресу и* омещается в оперативную память по ум-
пись-конец aarnvLНаконец> ка'< ^лъко будет прочитана г.-
ному в качестве я ,''.ПеРедает управление по адресу, задан-
адреса начала исполнения программы. На
£е загрузки СодеХм™" вы™Деть пио
которых нет записей в т“°в °б.лпастсй опе₽а?„[р™ма Р"с' 31а
Это означает, что перво,,??а?Р°ГРаммы, обоз“ХоТ™' дл»
памяти не менялось. Льное содержимОР ‘ “° Как
На рис. 3.2 показан алгопит» областей
загрузчика. Хотя данный ХХеаССМ°Трсн»°го нами п
один аспект, заслуживающий комм'<РаЙ"е пР°ст. всё Простого
рой программе каждый байт асс°ХТроРо™ „ В "аша« объТк?
НОГО кода дается в
begin
прочитать
проверить
прочитать
while тип
begin
запись-заголовок
имя и длину программы
первую запись тела программы
записи О 'Ez do
£К^^™±К0Л задан в ™"во*нон виде, то
прочитать следующую «явись объектной програи™,5™'"" "’hB™
передать управление по адресу, заданному в еаписе-понец
Рис. 3.2. Алгоритм абсолютного загрузчика.
шестнадцатеричном символьном ”Ре^ХАам^тТ?В№
часть объектной программы), они будуту
памяти. Однако в команде, ' ')“]°Р 3 за^'са11 в о<)«ол байте с
НИЯ, этот код операции должен бь образом каждая пара
шестнадцатеричным значением 14. 1,4 упакована во время
байтов объектной "Р.огРа”““ д“* 0 чётко понимать, что на
загрузки в один байт. Очень иа байт записи объ-
рис. 3.1а каждый символ предела -3jq каждый
ектной программы. С другой ciop- ‘ 1 цифру (т. с. пол-
' символ представляет одну шестнадцатеричную ц
ба дАный способ представлен.,язобъект^опрогр-мь.»-
эффективен как с точки зреши_ Поэтому в большинс
’ак и времени выполнения за ру ся в двоичном пРед^ 0
машин объектные программы . 1 'ктН0Г0 кода заппсыв“.
КйЙ, в котором каждый баи о ммы. Конечно,’ ,ю
'Виде отдельного байта °6^eK .KeT Содержать люоую . _ - 0
Представлении каждый бант может cWI цто в нмеЮщихс
величину. Мы должны оы. У лиформаиХ"»
Р1--— . программой п01"'^_р<-’^
. '» Напомним, что под <r,l5JcTUe исходных данны •
"Окупающая загрузчику р
системе соглашениях по работе с файлами и устройствами „
предусмотрено использование каких-либо кодов в качествеvn
равляющих символов. Например, соглашение, описание?
разд. 2.1 в котором в качестве признака конца записи исполь
зуется байт, содержащий шестнадцатеричное значение 00 м/
видно, не подходит для представления объектной программ,, й
двоичном виде. 1 ‘^ммы в
Очевидно, что объектная программа, хранимая в двоичном
виде, не годится для использования в книге, так как ее трудно
воспринимать читателю. Поэтому мы и далее будем пользо-
ваться в наших примерах символьным представлением объект
ных программ. 1
3.2. Машинно-зависимые свойства загрузчиков
Абсолютный загрузчик, описанный в разд. 2.1, конечно
весьма прост и эффективен, однако данная схема имеет ряд
потенциальных недостатков. Одним из наиболее очевидных яв-
ляется то, что от программиста требуется определять фактиче-
ский адрес начала загрузки программы во время ее ассембли-
рования. Если мы рассматриваем очень простую ЭВМ с
небольшим объемом оперативной памяти (такую, как стандарт-
ная модель УУМ), то это не создает особых проблем. В этом
случае места достаточно только для выполнения одной про-
граммы, и поэтому начальный адрес загрузки известен заранее.
Для более совершенных машин, обеспечивающих работу с
большим объемом оперативной памяти (подобных УУМ/ДС),
ситуация не столь проста. Очень часто желательно одновремен-
но выполнять несколько независимых программ, совместно
использующих оперативную память и другие ресурсы. Это озна-
чает, что мы не знаем заранее, куда будет загружена npoi ра -
ма. Поэтому для того, чтобы обеспечить эффективное раздс.н-
ние ресурсов машины, требуется создавать перемещаемые,
не абсолютные программы.
Абсолютные программы неудобны также и для исподы/»;-
ния в библиотеках стандартных подпрограмм. Количество лад
программ, содержащееся в большинстве таких библиотек I
пример, пакеты для научных или математических Расчеты
намного больше, чем требуется для каждой отдельно н
программы. Поэтому для того, чтобы эффективно использ ,
оперативную память, необходимо иметь возможность вькн,
только те подпрограммы, которые действительно нужны. -
лать это, если все подпрограммы должны загружаться с ;
нее назначенных адресов, весьма непросто. |1К
В этом разделе мы рассмотрим более сложный загр\-
Такой загрузчик вполне подходит для УУМ/ДС и яычж
с про.
типичным для большинства современных ЭВМ. Наряду с поо
стой функцией размещения программы в оперативной памяти'
описанной в предыдущем разделе, данный загрузчик выполняет
также перемещение и связывание программ. Одним из вопро-
сов, которого мы коснемся в данном разделе, будет вопрос о
влиянии структуры машины на решения, применяемые при про-
ектировании загрузчика.
Необходимость выполнения перемещения программ косвенно
связана с переходом на более мощные и большие ЭВМ. Кон-
кретный способ, используемый загрузчиком для реализации пе-
ремещения, зависит от структуры ЭВМ. Эта зависимость будет
рассмотрена в разд. 3.2.1. Мы обсудим различные технические
приемы, которые могут быть использованы для перемещения
программ, и укажем область их применения.
В разд. 3.2.2 разбирается процесс связывания программ с
точки зрения загрузчика. Функция связывания по сравнению с
перемещением обладает меньшей степенью машинной зависимо-
сти. Однако на практике для реализации обеих этих функций
очень часто используется один и тот же механизм. Кроме того,
процесс связывания обычно требует перемещения некоторых
подпрограмм. (См. приведенный выше пример использования
библиотечных подпрограмм.) Поэтому мы будем рассматривать
эти два процесса вместе.
В разд. 3.2.3 обсуждаются структуры данных и алгоритмы,
используемые в типичном связывающем (и перемещающем) за-
грузчике. Рассматриваемые здесь алгоритмы будут использова-
ны в последующих разделах в качестве отправной точки при
изучении более сложных возможностей, предоставляемых
грузчиком.
3.2.1. Перемещение
| Загрузчики, обеспечива^^ loaders) или
ваются перемещающими з PJ ( [ацие loaders). С к0”дсПр ' '
относительными ^грузчиками (^at^ в ра3д. 2Вам,
перемещения программ мы слетует бегло повторит
прежде чем продолжить.чтение; следуе „осо_
риал этого раздела. В да перемещении задается
ба, в которых информация аналоги-
ная часть объектной программы. способов в основном
каждого
. Первый из рассматриваемых Для описания
псп тому, что мы обсуж, ‘ ебуюЩег0 113меПьикатор. (Ее Фор*
Фрагмента объектного 1<од ’ иая Запись-модиф грамма для
Кении, используется специальная з3 „оказана "рт Рюстраипн
Мат описан в разд. 2-3'5 k„eM использовать Эт0 та же
УМ/ДС. которую м ы бУДем 0 „еремеш
рвого способа задания Ф
Строка Адрес Исходное предложение Объектный код
5 0000 СОРУ START 0
10 0000 FIRST STL RETADR 17202В 692020
12 13 0003 LDB BASE 4LENGTH LENGTH
15 20 25 30 35 40 45 50 55 0006 000А 000П 0010 0013 0017 001А 001В 0020 CLOOP ENDFIL +JSUK LDA COMP JEQ +JSUB LDA STA LDA RDREC LENGTH 40 ENDFIL WRREC CLOOP EOF BUFFER 43 AB101036 032026 290000 332007 4B101050 3F2FEC 032010 0F2016 010003 0F200D
60. 0023 STA LENGTH
65 70 0026 002А +JSUH J WRREC PRETADR АВ10105П 3E2003
80 002D EOF BYTE C'EOF' 454F46
95 0030 RETADR RESW 4
100 0033 LENGTH RESU 1
105 0036 BUFFER RESB 4096
110 »
115 я ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР
320 M
125 1036 RDREC CLEAR X B410
130 1038 CLEAR A B400
132 103А CLEAR S B440
133 103С +LDT ♦4096 75101000
135 1040 RLOOP TO INPUT E32019
140 1043 JEQ RLOOP 332FFA
145 1046 RD INPUT. DB2013
150 1049 COMPR A,S A004
155 104В JEQ EXIT 332008
160 104Е STCH BUFFER,X 57C003
165 1051 TIXR T B850
170 1053 JLT RLOOP 3B2FEA
175 180 1056 1059 EXIT STX RSUB LENGTH 134000 4F0000
185 105С INPUT BYTE X'Fl' Fl
195 200 ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 210 212 1050 105F WRREC CLEAR LDT X LENGTH B410 774000 Е32011 332FFA 53C003 BF2008 8850
215 1062 WLOOP TD OUTPUT
220 225 230 1065 1068 1068 JEQ LDCH wd WLOOP BUFFERrX OUTPUT
235 240 106Е 1070 TIXR JLT T «LOOP 3B2FEF 4F0000
245 1073 RSUB
250 1076 OUTFIT! ' BYTE X'05'
255 END FIRST 2.6).
Рис, 3.3. Пример программы для УУМ/ДС (с рис.
самая программа, что и на рис. 2.6. Здесь мы се 1И
дим исключительно для удобства. Большинство ком\./сТ1\С||ц\;
программы использует относительную или не1Ю^ни
адресацию, Единственной частью объектной програм.
жащей фактические адреса, являются команды, в котовых не
пользуется расширенный командный формат (строки 15 35 .
б5). Поэтому при перемещении программы изменение значений
потребуется только для этих величин.
На рис. 3.4 показана объектная программа, соответствую
щая исходному тексту на рис. 3.3. Обратите внимание что пл я
каждого значения, требующего изменения при перемещении
имеется отдельная запись-модификатор (в данном случае это
три ранее упомянутые команды). Каждая запись-модификатоо
определяет начальный адрес и длину поля, значение которого
НСОИУ ^>00000.00107 7
T/)t>0000AJDA17202DA69202DA4Bl01036A032026A290000A332007A4B10105D3F2FEC032010
Т00001 0.1 3AOF2016010003AOF200DA4B1 0 1 05 0дЗ Е200 3,4 54 F4 б'
^0103^1^B410AB400AB440A75101000AE32019A332FF4B2013AA004A332'008A57C003B850
TA001053AlDA3B2FEAA134000A4FOOOOAFlAB410A774000AE3201 1A332FFAA53C003DF2008Ba50
Т0010 70.07a3B2FEF4F000005 Л
Л Л Л Л
Jtf0000^05+COPY
FJOOOO 14ДО5+СОР Y
МОООО27дО5 + СррК
J^OOUOOO
Рис. 3.4. Объектная программа, в которой перемещение задается с помощью
записей-модификаторов.
необходимо изменить, а также тип требуемой модификации.
В данном примере все модификации заключаются в прибавле-
нии значения метки COPY, представляющей собой начальный
адрес программы. Алгоритм, используемый загрузчиком для вы-
полнения данной операции, описывается в разд. 3.2.3. Дополни-
тельные примеры определяемого подобным образом перемеще-
ния будут приведены в следующем разделе при изучении вза-
имосвязи между перемещением и связыванием.
Записи-модификаторы являются удобным средством для за-
дания информации о перемещении программы. Однако данная
схема годится не для всех машин. Рассмотрим, например, про-
грамму, приведенную на рис. 3.5. Это перемещаемая программа,
написанная для стандартной модели УУМ. Ее важным отличи-
ем от программы, изображенной на рис. 3.3, является то, что
стандартная модель УУМ не имеет относительной адресации
в дайной программе адреса всех команд, за искл^ч®”‘|(;
RSUB, должны модифицироваться при перемещении, оэ .
Для задания информации о перемещении необходимо им
запись-модификатор, что потребует более чем1 ДВ>КР‘*''‘ .. 0
личения объема памяти, занимаемой объектной пр р
сравнению с программой, показанной на рис. 3. .
Б Зак. 792
Строка Адрес Исходное предложение Объектной код
5 0000 COPY START 0
10 0000 FIRST STL RETADR 140033 Z ft 4
15 0003 CLOOP JSUB RDREC
20 25 0006 0009 LDA COMP LENGTH ZERO 481039 000036
30 35 000С 000F JEQ JSUB ENDFIL WRREC 280030 300015 481061 ЗС0003
40 0012 J CLOOP
45 50 0015 0018 ENDFJL LDA STA EOF BUFFER 00002A 0C0039
55 0018 LDA THREE 00002D
60 001Е STA LENGTH 0C0036
65 0021 JSUB WRREC 481061
70 0024 LDL RETADR 080033
75 0027 EOF RSUB 4C0000
80 002А BYTE C'EOF' 454F46
85 002D THREE WORK 3 000003
90 0030 ZERO WORD 0 000000
95 0033 RETADR RESW 1
100 0036 LENGTH RESW 1
105 0039 BUFFER RESB 4096
110 *
115 » ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР
120 w
125 1039 RDREC LDX ZERO 040030
130 103С LDA ZERO 000030
135 103F RLOOP TD INPUT Е0105П
140 1042 JEQ RLOOP 30103F
145 1045 RD INPUT 88105»
150 1048 COMP ZERO 280030
155 104В JEQ EXIT 301057
160 104Е STCH BUFFERrX 548039
165 1051 TIX MAXLEN 2C105E
170 1054 JLT RLOOP 38103F
175 1057.. EXIT STX LENGTH 100036
180 105А RSUB 4C0000
185 105D INPUT BYTE X'Fi' Fl
190 105Е MAXLEN WORD 4096 001000
195 200 Л a ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА
205 210 106t URREC LDX ZERO 04003® E0107? 301064 50803? IIC10791 2C003& 381064 4C0000
215 1064 ML OOP TD OUTPUT
220 1067 JEQ WLOOP
225 106А LDCH BUFFERу X
230 106D WD OUTPUT
235 1070 TIX LENGTH
240 1073 JLT WLOOP
245 1076 RSUB
250 1079 OUTPUT BYTE X'05' vj
255 END FIRST модели УУМ.
Рис. 3.5. Перемещаемая программа для стандартной
_ .-j I.
На машинах, где преимущественно используются прям.
ресация и фиксированный командный формат, очень ч. с
лее эффективным оказывается другой способ задания и qi
ции о перемещении. На рис. 3.6 показано, как этот сном
жет быть применен к нашему примеру. В данном случ‘
(.«-модификаторы не используются. Формат записей тела пп
граммы тот же, что и ранее, за исключением того, что тепепк
<• каждым словом объектного кода связан разряд п'
Поскольку все команды УУМ занимают одно слово это <Х
чает, что для каждой потенциальной команды имеется отий
разряд перемещения. Эти разряды собираются вместе и обоз
зуют маску, которая записывается после указателя длины кя₽ж
дой записи тела программы. На рис. 3.6 эта маска (в символ^’
ном виде) показана в виде трех шестнадцатеричных цифв (1|а
рисунке они подчеркнуты). vld
Если разряд перемещения установлен в 1, то при перемеще-
нии программы начальный адрес программы добавляется к ело
ву, соответствующему этому разряду. Значение разряда пеое-
мещения, равное 0, показывает, что никаких преобразований
BCOPY ^00000^01074
TOOOOOO^lEFFC^l 400 3348 1039л000036л2ао030лэ00015л48 106 1ЛЗСОООЗЛ00002АОС003900002В
1)0001 Е15,Е00.0С0036л48 106 1Л080033Д4С0000.454Г46.000003.000000 ' Л
^0!039л1^2С040030лООООЗОлЕ01050л30103КлП81050л280030л301057л548039г2С105Ел38103Е
70010 5 7.0 Ад8 0 0,10 0 0 3 6д4 С 0 00 0д РI л00 10 0 0
700106 1.19ГЕО.О4ООЗО>ЕО1О7 9лЗО1О^4л5Ь8039РС107 9.2С0036.381О644СО0ОООЧ
л Л ‘Л """7V ' А А л Л Л Д Д
^оооооо
Рис. 3.6. Объектная программа, в которой перемещение задается с помощью
маски перемещения.
при перемещении делать не надо. Если запись тела программы
содержит менее 12 слов объектного кода, то разряды, соответ-
ствующие неиспользуемым словам, устанавливаются в 0. Таким
образом, в первой записи тела программы маска FFC (пред-
ставляющая собой строку 111111111100) показывает, что все
Ю слов объектного кода должны быть модифицированы при
перемещении программы. В данных словах находятся команды,
соответствующие в исходной программе строкам с 10 по 55 (см.
рис. 3.5). Маска Е00 во второй записи тела программы опре-
деляет, что модификация требуется для трех первых слов.
Оставшаяся часть объектного кода в данной записи представ-
ляет собой константы (и команду RSUB), не требующие моди-
фикации.
Аналогично строятся остальные записи тела программы.
Ратите внимание, что объектный код, генерируемый для
™ LDX в строке 210, начинает новую запись тела программы.
*отя в предыдущей записи достаточно места для его 1 ‘
яИя. Это произошло потому, что каждый разряд пеР^' j в
«язан с 3-байтовым сегментом объектного кода (“ов ’це0
аписн тела программы. Поэтому каждое значе , У[1М из
Модификации при перемещении, должно совп д ’ было
3-байтовых сегментов для того, чтобы ему можно
на^кГм^
ку в ней используется прямая адресация Однако ™ТОЛЬ'
была помещена в предыдущую запись тела прогпамм,
была бы правильно выравнена для соответствия “е
мещения, так как в строке 185 была сгенерировав ? ЛУ- ПерС‘
константа. Поэтому данная команда должна начинать в обТТит*
нои программе новую запись тела программы.
ам следует тщательно изучить оставшуюся часть объектной
программы на рис. 3.6 и разобраться с тем, как ассембпеГ
нерирует разряды перемещения и как они используются за^з-
Некоторые ЭВМ предоставляют аппаратные средства облег-
чающие организацию перемещения программ. Например в не-
которых машинах все ссылки к оперативной памяти рассмат-
риваются как относительные ссылки с базовым адресом, назна-
чаемым пользователем. Преобразование этих относительных
адресов в физические производится во время исполнения про-
граммы. (Мы обсудим этот процесс позднее — при разборе
управления оперативной памятью в гл. 6.) Однако, как мп
увидим в следующем разделе, загрузчик тем не менее должен
выполнять некоторые функции перемещения подпрограмм для
обеспечения их связывания.
3.2.2. Связывание программ
С основными концепциями, затрагивающими связывание
программ, мы познакомились в разд. 2.3.5. Прежде чем про-
должить чтение, вам следует повторить материал этого раздел1
и еще раз посмотреть приведенные там примеры. В дашк
разделе мы обсудим более сложные примеры внешних ссылок
между программами и изучим взаимосвязь между перс-нп.
см и связыванием. В следующем разделе дается onHCJ‘1’^ *.
горитма загрузчика, обеспечивающего связывание и шр
На рис. 2.15 в разд. 2.3.5 была показана программа, со
щая из трех управляющих секций. Эти управляют ‘
могут ассемблироваться как вместе (т. е. за одно оf <
ассемблеру), так и независимо друг от друга. Б люб _ с.
после ассемблирования они будут представлены 0'., •
вых сегментов объектного кода (рис. 2.17). ; ‘ ' в вц.;
мист, естественно, склонен рассматривать ПР Р * е vir;; •
логического целого, включающего в себя все св никак
ляющие секции. Однако с точки зрения загру |(
программы нет вообще. Имеются только УпРавл/^ тьсЯ.
которые должны связываться, перемещаться и загруз н Ве
грузчик никоим образом не может узнать (да
н-
ь-
ie
я
нужно) о том, какие управляющие секции ассемблировались
одновременно.
рассмотрим три (раздельно ассемблированные) программы,
изображенные на рис. 3.7. Каждая из них состоит из единствен-
ной управляющей секции и содержит списки (LISTA, LISTB,
LiSTC). Концы этих списков помечены метками ENDA, ENDB,
FNDC. Метки в начале и в конце списков являются внешними
менами (т. е. они доступны для связывания). Обратите вни-
мание, что каждая программа содержит один
сылок к этим внешним именам. Три из них
манд (предложения с метками REF1
11 тот же набор
____ . РЕР'Ъ 0ПСРа1'АЫ ко-
ссылки на элементы данных „ ’’ а остальные —
REF8). На данном примере мы посмотп..^''0 сл0“° <REF« -
личия в обработке этих иден?и‘шыГвырМа’женийМ B°v^Lpa3'
трех программах, и подчеркнем взаимосвяМ Указанных
'— — - -—- - - - - - - _ . _ ___ сосредоточиться6 иТ’дщъ
пом вопросе, мы сознательно не стали приводить реальные про-
граммы. Те части программ, которые не используются
цессах перемещения и связывания,
В Про-
опущены. То же самое
относится и к сгенерированному для этих программ объектному
коду (см. рис. 3.8).
Рассмотрим вначале предложение с меткой REEL Для пер-
вой программы (PROGA) REF1 является просто ссылкой на
метку внутри данной программы. Она ассемблируется обычным
образом как команда, использующая адресацию относительно
счетчика команд. Никаких модификаций для перемещения или
связывания не требуется. В PROGB, с другой стороны, тот же
самый операнд ссылается на внешнее имя. Ассемблер исполь-
зует для этой команды расширенный командный формат и за-
носит в адресное поле значение ОООООО. Соответствзюшая с
объектная программа (см. рис. 3.8) содержит щп к „ енне
катор, в котором загрузчику предписывается Д < связывания
имени LISTA к данному адресному полю » ба1 Ь1вастся
программы. Совершенно аналогично эта сс .
для PROGC. -млигя r команде с мст-
Похожим образом обрабатывается ’ в качестве one-
кой REF2. В PROGA выражение, ЛК1| „ константы,
ранда, представляет собой сумму в {ТЫ в адресном поле
Ассемблер запоминает величину .васт загрузчику доба-
команды, а запись-модификатор р PROGB то же самое
вить к данному полю значение, ' ’й и поэтому обрабачы-
выражение является локальной нсм адресации 01Н(*
ваАся обычным образом с исп“ьзова.^ „„ связывания здесь
тельно счетчика команд. Ни Р гтвецный
не требуется. RFF3 используется непоср^у ENDA
В команде с меткой ° ляется разность межд.
Операнд, значением которог _ ___
Адрес Исходное предложение Объектный код
€000 PROGA START 0 EXTDEF LISTA.EMOA EXTREF LISTB,ENDB,LI3TC,ENDC > •
€020 €023 €027 0040 REEL REF2 REF3 LISTA LDA 4LDT LDX a • EQU a LISTA LISTB+4 ♦ENDA-LISTA * 0320ID 77100004 050014
0054 ENDA EQU *
0054 REF4 WORD ENDA-LISTA+LISTC 000014
0057 REFS WORD ENDC-LISTC-10 FFFFF6
005A REF6 WORD ENDC-LISTC+LISTA-1 00003F
0050 REF7 WORD ENDA-LISTA-(ENDB-LISTB) 000014
0060 REF8 WORD LISTB-LISTA FFFFC0
END REFI
Объектный код
Адрес
Исходное предложение
0000 PROGS START 0
EXTDEF LISTB,ENDB
EXTREF LISTA,ENDA,LISTC,ENDC
0036 003A 003D REFI REF2 REF3 +LDA LDT +LDX • LISTA LISTB+4 ♦ENDA-LISTA «3100000 772027 «5100000
0060 LISTS • EQU • *
0070 O070 0073 0076 0079 007C ENDB REF4 REFS REF6 REF7 REF8 EQU WORif WORD WORD WORD WORD END M ENDA-LISTA+LISTC ENDC-LISTC-10 ENDC-LISTC+LISTA-1 ENDA-LISTA-(ENDB-LISTB) LISTB-LISTA 000000 FFFFF6 FFFFFF FFFFF0 000060
Рис. 3.7. Модельная программа, иллюстрирующая связывание и |И11
3-2' Машинно-Зависимые свойства загрузчиков
— — >35 Адрес Исходное предложение
W.» F'ROCC START » «"»
EXTDEF LISTC,ENDC
EXTREF LISTA,ENDA,LISTB,ENDS
» *r
0018 REFI +LDA LISTA
001C REF2 +LDT LISTB+4 «310000ft
«020 REF3 +LDX «ENDA-LISTA 77100004'
. 05100000
0030 LISTC EQU м
«042 ENDC EQU *
0042 REF4 WORD ENDA-L ISTA+LT^Tr» «045 REF5 UORB ENDC-LISTC-10
«048 REF6 WORD ENDC-LISTC+LISTA-t 000008 s s =
Рис. 3.7. Продолжение.
и LISTA (т. е. длина списка в байтах). В PROGA ассемблер
располагает всей необходимой информацией для вычисления
этого значения. Однако при ассемблировании PROGB (и
PROGC) значения меток неизвестны. В этих программах выра-
жение должно вычисляться как внешняя ссылка (с двумя
записями-модификаторами) даже несмотря на то, что в конеч-
ном счете результат является абсолютной величиной, не зави-
сящей от места загрузки программы.
Оставшиеся ссылки иллюстрируют другие возможные вари-
анты. Общий подход, принятый при ассемблировании, заключа-
ется в том, что ассемблер стремится вычислить как можно
большую часть выражения. Оставшиеся термы передаюich за-
грузчику с помощью записей-модификаторов. Для toio чтобы
разобраться в этом, рассмотрим предложение с меткой RL1
В PROGA ассемблер может вычислить все выражение, за иск-
лючением значения LISTC. В результате имеем начальное зна-
чение 000014 (шестнадцатеричное) и одну запись-модифпка о.,.
Однако в PROGB то же самое выражение не содержит ни о -
ного терма, который может быть вычислен ассем1
этому объектный код будет содержать иачаЛррПС/ ассемблер
ное боОООО, и три записи-модификатора В
знает относительное значение LISI С (но < будет
рес, который неизвестен до тех пор, пока 11 констаУнты
загружена в память). Начальное значен (шестнадцатерич-
будет содержать относительный адрес L I -одержат указа-
ная величина 000030). Записи-модифик Р грРммы (т. с.
ния загрузчику прибавить начальный ад!
RPROCA 000000A000063
DLISTA L)OOOA05ENDA ^00054
\JASTB akndb alistc aendc
7000020^03201 DJ7 100004л050014
•
^ло о О 0 5 401^0 0 О 01 4 F p F P F 6 0 о и V j r.u 00 01 АР г f f c 0
Mp000 24A0 5A+LI STB л л
Нл00005Ал06а+Ы STC
B^OOOS 7ЛО6^ENDC
MOOOO5 7A0^~LI STC
RpOOO 5 APttf ENDC
HpOOO5A,p^-LI STC
>!лОООО5 AD 6Л PROGA,
fy0Q005DA06A-£NDB
HU0005Da06^LIST8
h/)0oo6q.o6r+LiSTB
НрОООбо'Об,-PROGA
I#00J)2v/'
№*ДО C iTTO00oqpd007 k
DL1STB 000Q60aENDB /Э00070
J^LISTA^NbA AUSTC£NDC
Т4о 00 0 3 6л0 Вл0 310 0 0 0 0л7 7 2 0 2 7л0 510 0 0 0 0
MOO07<KOFAOOO0O(U?nFF6jrmXmfF(l!)00Q6O
*£OOO37aO5a+LISTA
K£0003E£5atENDA
>\p0003EA0 54-LISTA
M£00070£6a+ENDA
)ф00070л06л-1Л5ТА
>Ц)00070Д6Л+И5ТО
ИОООО71О6ЛЕКВС
KOOOO71O6a-LISTC
Цр0007^06л+ЕЫСО
Мр0007 6.06л-1Д STC
Кр0007«$6л+Ы STA
MOO(IO79AOa+ENDA
*£OOO79O6-LISTA
H000Q7Ca06+PROGB
H00007c06-tISTA
Л Л
HJPHOCC Л000000Л000051
DJjISTC OOOQ3OENDC 000042
^ISIA ЕНОЛ LISTB^NDH
W000180C03100000771000D405100000
А Л Л Л А
•
трооо4локоооозо.оооооароооплоооооооооооо
j(pOOO|9AO5A-4-l.lSTA
Мрооо 1ЪдО5+1Д5Тв
*£0002 Ja05.+ENDA
J$0002Lo£-HSTA
*$0004206+ENDA
*£0004 2£6~LISTA
*£00042A06+EROCC
*£0004ВА06А+ТД STA
*£0004Ba06>ENDA
)^)0004^o£-LISTA
>(pOOO4 ^06-ENDB
*£0004B,06A+LISTB
*£0004E$6+L I ST В
Xp0Q04f£o£-n6IA
значение PROGC), приба-
вить значение ENDA и вы-
честь значение LISTA. Та-
ким образом, выражение
REF4 представляет собой
простую внешнюю ссылку в
случае PROGA, более
сложную внешнюю ссылку
в случае PROGB и комби-
нацию перемещения с внеш-
ней ссылкой в случае
PROGC.
Вам следует самостоя-
тельно разобраться с остав-
шимися ссылками (с REF5
по REF8) и убедиться, что
вы правильно поняли, как
были сгенерированы объ-
ектный код и записи-мо-
дификаторы, показанные на
рис. 3.8.
На рис. 3.9а приведены
три рассмотренные нами
программы после загрузки
и связывания. Программа
PROGA была загружена,
начиная с адреса 4000. Не-
посредственно после нес
были загружены PROGB и
PROGC. Заметим, что в ре-
зультате (после перемеще-
ния и связывания) каждое
выражение с REP4 по
REF8 будет иметь одно и то
же значение во всех трех
программах. Так и должно
было быть, поскольку в ис-
ходных программах он *
имели один и тот же вид
Рассмотрим, например
значение метки REI 4
PROGA. Она расположена
по адресу 4054 (этот адр1
Рис. 3.8. Объектная программ3'
соответствующая рис, 3.7,
’ Адрес
Содержимое
оооо ХХХХ хххх хххххххх хххххххх хххххххх
• • • •
• • • •
• • • • •
3FF0 ХХХХХХХХ хххххххх ХХХХХХХХ Хххххххх
4000
4010 а. ••••*.
4020 03201D77 1О4ОС7О5 0014 ... . PROG А
4030 • «•....а
4040
4050 00412600 00080040 51000004
4060 000083|. > ta.taaa. • •••»•*»
4070 • ••ta*aa ааа.а.а. Л А. — Л _ — -
4080 • ••«••а • ...«..а жааа.а..
4090 • ••••••а а.031040 40772027
40А0 05100014 4- PROGB
40В0 .....«•а а.аааааа
40С0 ааааа*.4 а....... *..а4.а. • •«•а...
40D0 00 41260000 08004051 00000400
40Е0 OO63f. . . . *«...••«
40F0 • »••••• «аа.аа.а . а а .0310 40407710
4 100 40С70510 0014 ... ф 4-PR0GC
4 110 «••••«* аааааааа • а*.ааа»
4120 00412600 00080040 51000004
4130 000083|хх хххххххх хххххххх хххххххх
4 140 • хххххххх. хххххххх хххххххх хххххххх
Объектная программа содержимое памяти .
Рис. 3 9а. Программа рис. 3.8 после связывания и загрузки. 3.96.
операций связывания и перемещения для предложения REF4 из I КОО. •
вычисляется как сумма начального адреса PROGA к
относительного адреса REF4, равного 0054) На рис 3 96
нТиЛТип показаи пР?цесс вычисления этого значения.
Начальное значение (полученное из записи тела про-
граммы) равно 000014. К нему прибавляется адрес
назначенный метке LISTC и равный 4112 (начальный
адрес PROGC плюс 30). В PROGB значение REF4 расположено
по относительному адресу 70 (фактический адрес 40D3) К на-
чальному значению (000000) загрузчик прибавляет значения
меток ENDA (4054) и LISTC (4112), а затем вычитает значе-
ние метки LISFA (4040). В результате будет получено значе-
ние 004126, т. е. точно такое же, как и в PROGA. Значение
REF4 в PROGC вычисляется аналогично и дает тот же самый
результат. Те же самые рассуждения справедливы и для всех
других меток с REF5 по REF8.
Если одно и то же выражение используется в качестве опе-
ранда в различных командах, то после загрузки адресные поля
этих команд необязательно должны иметь одинаковые значе-
ния. Это происходит потому, что при вычислении адреса опе-
ранда для команд, использующих адресацию относительно счет-
чика команд (или базы), выполняется еще один дополнитель-
ный шаг. В данном случае важно, чтобы совпадали целевые
адреса команд. Например, в PROGA команда с меткой REF1
использует адресацию относительно счетчика команд. Значение
смещения для данной команды равно 01D. В момент исполне-
ния этой команды в счетчике команд будет находиться величи-
на 4023 (фактический адрес следующей команды). В резуль-
тате будет получен целевой адрес 4040. Данная команда не
требует какой-либо модификации при перемещении программы,
так как счетчик команд всегда будет содержать фактический
(а не относительный) адрес следующей команды. Мы можем
рассматривать данный процесс как автоматическое выполнение
требуемого перемещения в момент исполнения программы п\-
тем вычисления целевого адреса. С другой стороны, в програм-
ме PROGB команда с меткой REF1 использует расширенны
командный формат, в котором фактический адрес задается не-
посредственно. После связывания значение данного адреса о
дет равно 4040, т. е. будет совпадать со значением целев".
адреса соответствующей команды PROGA.
Вам следует тщательно разобраться с остальными пред*
жениями и убедиться, что целевые адреса (в случае RE1-
REF3) и значения констант (для REF5—REF8) одни и
в каждой из трех программ. Сейчас вас не должно беспокоя
как загрузчик реально выполняет данные вычисления, посьо. •’
ку необходимые для этого алгоритмы и структуры данных 1
дут обсуждаться в следующем разделе. Важно, однако, чв'
вы поняли, какие именно вычисления надо делать и могли ни
полнить их вручную (следуя при этом инструкциям, содеожа.
щимся в объектных программах). 1
3.2.3. Таблицы и алгоритмы связывающего
загрузчика
Теперь мы готовы к тому, чтобы рассмотреть алгоритм ра-
боты связывающего (и перемещающего) загрузчика. Мы будем
использовать записи-модификаторы таким образом, чтобы функ-
ции связывания и перемещения выполнялись с помощью одного
и того же механизма. Как уже упоминалось, данный тип за-
грузчиков часто применяется для машин (подобных УУМ/ДС),
которые используют относительную адресацию и тем самым де-
лают перемещение большинства адресов ненужным.
Алгоритм связывающего загрузчика значительно более сло-
жен, чем алгоритм абсолютного загрузчика, который мы рас-
сматривали в разд. 3.1. Входная информация для этого загруз-
чика состоит из набора объектных программ (т. е. управляю-
щих секций), которые должны быть связаны друг с другом.
В управляющих секциях могут использоваться (и это обычная
ситуация) внешние ссылки па имена, значения которых во
входном потоке еще не были определены. В этом случае тре-
буемое связывание не может быть выполнено до тех пор, пока
не будут назначены адреса для всех требуемых имен (т. е. до
тех пор, пока не будет прочитана требуемая управляющая сек-
ция). Поэтому связывающий загрузчик обычно выполняет два
просмотра входного потока точно так же, как это делает ас-
семблер. В общих чертах эти два просмотра, выполняемые
связывающим загрузчиком, имеют много общего с двумя про-
смотрами, выполняемыми ассемблером: во время первого про-
смотра назначаются адреса для всех внешних ссылок, а во
время второго выполняются фактическая загрузка, перемеще-
ние и связывание.
Основная структура данных, необходимая для связывающего
загрузчика,— это таблица внешних имен (ESTAB). Данная
таблица является аналогом SYMTAB ассемблера и использует-
ся для хранения имен и адресов всех внешних ссылок для все-
го набора управляющих секций, загружаемых совместно. Очень
часто в этой таблице также запоминается информация о том,
какая управляющая секция содержит определение имени. Обыч-
но ESTAB организуется в виде хеш-таблицы. Двумя другими
важными переменными являются PROGADDR (адрес загр^зю
программы) и CSADDR (адрес управляющей секции). Перемен-
ная PROGADDR —это адрес начала программы в оперативно!
памяти, куда должна загружаться связываемая программа.
Pass 1:
begin
получить PROGADDR от операционной системы
”р“й«""»'« -->
begin
прочитать следующую входную запись
{запись-заголовок управляющей секции!
занести в CSLTH длину управляющей секции
поиск имени управляющей секции в ESTAB
if нашли then
занести признак ошибки (дважды
else
занести имя управляющей секции
while тип записи О 'Е' do
begin
определенное внешнее мня)
в ESTAB со значением CSADDR
прочитать следующую входную запись
if тип записи = 'D' then
for для каждого имени записи do
begin
поиск имени в ESTAB
if нашли then
занести признак ошибки
(дважды определенное внешнее имя)
else
занести имя в ESTAB со значением
(CSADDR + указанный адрес)
end (for!
end Cwhile <> ZE'}
прибавить CSLTH к CSADDR
{начальный адрес следующей управляющей секции!
end {while не конец!
end (Pass 1}
Рис. 3.10а. Алгоритм первого просмотра связывающего загрузчика.
адрес загрузчик получает от операционной системы. (В гл. 6
мы обсудим, как операционная система может определить
PROGADDR.) Переменная CSADDR содержит начальный адрес
той управляющей секции, которая обрабатывается загрузчики^
в данный момент. Этот адрес добавляется ко всем относит еди-
ным адресам данной управляющей секции для того, чтобы про-
образовать их в фактические адреса.
Сам алгоритм показан на рис. 3.10а и 3.106. В процессе
обсуждения этого алгоритма вам, возможно, будет полезно
вспомнить примеры загрузки и связывания, рассмотренные г-
предыдущем разделе (рис. 3.8 и 3.9).
Во время первого просмотра (рис. 3.10а) загрузчик обраба-
тывает только запись-заголовок и записи-определения управля-
ющих секций. Начальный адрес загрузки связываемой прогр 1
мы (PROGADDR) загрузчик получает от операционной систем
Этот адрес становится начальным адресом (CSADDR) иертч '
управляющей секции входного потока. Имя управляющеч А
ции, полученное из записи-заголовка, записывается в ESTAB 11
Pass 2:
Ut
begin
занести в CSADDR значение PROGADDR
занести в EXECADDR значение PROGADDR
while не конец входного потока do
begin
прочитать следующую входную запись (запись-
занести в CSLTH длину управляющей секции
while тип записи О do
заголовок!
begin
прочитать следующую входную запись
if тип записи « 'V then
begin
если объектный код представлен в символьном
виде, то преобразовать его во внутреннее
представление)
занести объектный код записи по адресу
(CSADDR 1 указанный адрес)
end (if 'D
else if тип записи « 'К' then
begin
поиск модифицируемого имени в ESTAB
if нашли then
прибавить или вычесть значение имени к адрбСУ
(CSADDR + указанный адрес)
else
занести признак ошибки
(неопределенное внешнее имя)
end (if 'М')
end (while О 'Е')
if адрес определен ( в записе-конец ) then
занести в EXECADDR значение (CSADDR + указанный адрес)
прибавить CSLTH к CSADDR
end (while не конец)
перейти по адресу/ заданному в EXECADDR (начать исполнение программы!
end (Pass 2!
Рис. 3.1 Об. Алгоритм второго просмотра
связывающего загрузчика.
ему присваивается текущее значение CSADDR. Все внешние
имена из записей-определений также заносятся в ESI АВ. Зна«
чения их адресов получаются путем сложения значения из
записи-определения с CSADDR. После того, как будет прочи-
тана запись-конец, к CSADDR добавляется длина управляющей
секции (CSLTH). (Длина была получена из записи-заголовка.)
Таким образом, мы получаем начальный адрес для следующей
управляющей секции.
После завершения первого просмотра ESTAB содержит все
внешние имена, определенные в данном наборе управляющих
секций, вместе с назначенными им адресами. Многие загрузчи-
ки могут по желанию пользователя выдавать на печать табли-
цу загрузки, в которой показаны внешние имена и их адреса.
Эта информация часто используется для отладки программ.
Для примеров, приведенных на рис. 3.8 и 3.9, такая ia vn
загрузки может выглядеть следующим образом:
Управляющая секция И м я Адрес Длина
PROGA LISTA 4000 4040 0063
PROGB ENDA LISTB 4054 4063 40C3 007 F
PROGC ENDB 40D3 40E2 0051
LISTC 4112
ENDC 4124
По существу это та же информация, которая содеожится к
ESTAB в конце первого просмотра. V
Собственно загрузка, перемещение и связывание программы
осуществляются во время второго просмотра (рис. 3.106). Пе-
ременная CSADDR используется так же, как и во время пер-
вого просмотра. Она всегда содержит фактический начальный
адрес загружаемой в данный момент управляющей секции. По-
сле того, как считана очередная запись тела программы, содер-
жащийся в ней объектный код помещается по указанному ад-
ресу (плюс текущее значение CSADDR). Когда встречается
запись-модификатор, то имя, требуемое для модификации, ищет-
ся в ESTAB и затем его значение прибавляется к заданному
адресу или вычитается из него.
Завершает свою работу загрузчик обычно передачей управ-
ления на загруженную программу. (В некоторых системах на-
чальный адрес программы просто возвращается операционно'!
системе и пользователь должен затем выполнить отдельную
команду для начала выполнения программы.) Запись-конец
каждой управляющей секции может содержать адрес первой
команды данной секции, с которой должно начинаться ее ис-
полнение. Наш загрузчик рассматривает этот адрес как адрес
передачи управления для исполнения программы. Если адрес
передачи управления задан более чем в одной управляют.1-'
секции, то загрузчик использует последний встретившийся.
Если ни одна из управляющих секций не содержит адрес
редачи управления, то загрузчик использует в качестве a ipo-
передачи управления начальный адрес программы U
PROGADDR). Это соглашение типично для большинства связы-
вающих загрузчиков. Обычно адрес передачи управления
жен помещаться только в записи-конце главной программы,
не в подпрограммах. В этом случае стартовый адрес будет ци -
вильно определяться вне зависимости от порядка следоваш
управляющих секций. (См. пример на рис. 2.17.)
Вам следует применить данный алгоритм (вручную)
вагрузки и связывания объектной программы, изображенной
рис. 3.8. Если для PRO-
GADDR использовать 4000,
то полученный результат
должен быть таким, как
показано на рис. 3.9.
Можно несколько повы-
сить эффективность данного
алгоритма, если слегка из-
менить формат объектной
программы. Суть этих из-
менений заключается в том,
что каждой внешней ссылке
присваивается специальный
ссылочный номер. Эти ссы-
лочные номера использу-
ются в записях-модификато-
рах вместо имен.
Предположим, что имя
управляющей секции всег-
да имеет ссылочный номер
01. Ссылочные номера ос-
тальных внешних ссылок
определены в записи-ссылке
объектной программ дан-
ной управляющей секции.
На рис. 3.11 показано, как
будет выглядеть объектная
программа, изображенная
на рис. 3.8, после внесения
в нее указанных изменений.
Для удобства чтения объ-
ектной программы ссылоч-
ные номера подчеркнуты.
Описанный здесь механизм
часто используется в реаль-
ных загрузчиках, и это бы-
ла одна из причин, почему
мы включили в наше объ-
ектное представление за-
писи-ссылки. Вы могли
Рис. 3.11. Объектная програм-
ма, соответствующая рис. 3.7,
в которой используются
ссылочные номера для моди-
фикации кодов. (Для удоб-
ства чтения ссылочные номера
подчеркнуты.)
ItfROCA />00000,00006 3
I/LISTA. POOOAC^ENDA. />00054
R.02LISTB .ОЭЕНРа f041,ISTC ftSEHDC
ш
7000020.0X03101 D7710000405001 4
Л Л Л Л
л
T00D054OF0O0014FFFFF6PQQQ3FOOQ014FFEFCQ
M>OQO2<OS+O2 Л А Л Л
Мрооо 54 06,4-04
ИрООО 5 7.06 + 0 5
ироооьлоб^оч
Н00005АР6+05
Н0000ЬА.06-04
BpOOUSAp^QL
Н00005Рл06-0Э
K00005D06A+0_Z
У000060рбл+02_
ЙО 000 6 0*06.-0.1
lz000_020 2________
BPROGB ООООбОАОООб7>
11LISTB .OOOO6OZENDB £00070
K02LISIA л03ЕМ)Л \O4L1STC р5ЕКЪС
Т000036л0 Вд0310000077 2027л05100000
HOOoS3 7O5,2o?000/>FFn£^F?ff^FfffV00560
МРОООЗ^О 5^+03
НДОООЗЕ.р 5-0Т
ДО 00 07 0,06.-603
эфооо7йОбА-иг
Х00007о'06.+ 04
Н.О 000 73.0 6,+ оТ
Ир001)73,0(^-04
Я00007бЬб.+о?
Н00007 6/) 6-04
нл00007 6л0б'+02
МР00073,0&ОЭ.
00079.06-02
тфооо 7СлО6ч+О_Е
»#0007<^6л-О2
к
H.PROCC Д00000.000031
ftLISTC /J00030.ENDC 000042
J£2L1STA £JENPA ££11 STB ДИЯМ
•
T.0000180C03100000.771000D405100000
тоооо4 2рЕоооозолооооовчоооои,оооооо.ооооо9
MJ)QO 01 ЯО 5.+о 2
Н00001 D.05.+ 0 4;
МР0002]А05>0 3.
2100002 1.0Д.-02.
вр0004 2л0б.+ 0/
ноооОЩбгог
*00004
M.0QQ04 8j06.4 0 Л
НООООАВ^б + ОД
М.00004 KU6x-0 2
м.р оо о 4 в,Ь&-оЗ»
м.00004 вр 6,
МЛ0004Ер6+04
мЬ0Р04еМ~О2
Е
заметить, что в алгоритме на рис. 3.10 эти записи не использо-
в л л псь.
Основное преимущество использования ссылочных номеров
заключается в том, что в этом случае отпадает надобность в
многократном просмотре ESTAB для одних и тех же имен Все
внешние ссылки, которые используются в данной управляющей
секции, могут быть найдены в ESTAB один раз. Затем когда
это потребуется, значение внешней ссылки можно получить по
со индексу в массиве ссылок. Вам предлагается разработать
алгоритм, в котором используется такой механизм, и подумать,
какие для этого потребуются дополнительные структуры
данных. 1
3.3. Машинно-независимые свойства
загрузчиков
В этом разделе мы обсудим некоторые свойства загрузчи-
ков, которые непосредственно не связаны со структурой машины.
Загрузка и связывание часто рассматриваются как сервисные
функции операционной системы. Взаимодействие програм-
миста с загрузчиком менее тесное, чем, скажем, его взаимодей-
ствие с ассемблером во время создания программы. Поэтому
большинство загрузчиков имеет лишь незначительные особен-
ности (и меньше различается по своим возможностям, чем ас-
семблеры).
В разд. 3.3.1 мы обсудим использование автоматического по-
иска программ в библиотеках для разрешения внешних ссылок.
Это средство позволяет программисту использовать ci айда pi
ные подпрограммы, не включая их явным образом в за! р\ /ь '•
мую программу. Подключение библиотечных подпрограмм
ществляется автоматически во время связывания.
В разд. 3.3.2 рассматриваются некоторые наиболее ио
употребительные дополнительные средства, которые, пр*’!,
использовать по своему усмотрению во вРе'
связывания программ. Эти средства ВК‘Г11ОЧ;''(
мист может
загрузки и
возможность
информации,
источника
ВХОДНОЙ
задания альтернативного
изменение или уничтожение внешних ссыл<
обработкой £ " •
внешних
также управление автоматической
ссылок. inivieii-
В разд. 3.3.3 мы более детально изучим концепцию 01
ной загрузки программ, с которой мы познакомили '
разд. 2.4.1. Мы обсудим способы задания оверлейной еррьг
и рассмотрим, как она может быть реализована в проид<
выполнения программы.
3 3 Мп1Ц||""° независимые свойства зсгрузчикоп
3.3.1. Автоматический поиск в библиотеках
Многие связывающие загрузчики допускают аптлмпт-,
включение библиотечных подпрограмм в загружаемую програм
му. В большинстве случаев для этой цели используется некого'
рая стандартная библиотека. Другие библиотеки могут поХо
чаться с помощью специальных управляющих директив или не
редаваться загрузчику в качестве параметров. Этот механизм
позволяет программисту использовать подпрограммы из одной
или нескольких библиотек (например, математические или ста
тистические подпрограммы) почти так же, как если бы они
были составной частью языка программирования. Подпрограм-
ма, вызываемая^ из загружаемой программы пользователя, ав-
томатически выоирается из библиотеки, связывается с главной
программой и загружается в оперативную память. От програм-
миста не требуется ничего, кроме как перечислить имена ис-
пользуемых подпрограмм в исходной программе в списке внеш-
них имен. В некоторых системах данный механизм называется
автоматическим библиотечным вызовом {automatic library
call). Мы используем термин библиотечный поиск (library
search) для того, чтобы не путать его со средствами вызова,
которые имеются в большинстве языков программирования.
Связывающие загрузчики, поддерживающие библиотечный
поиск, должны иметь список всех внешних имен, на которые
есть ссылки, но которые не были определены во входном пото-
ке загрузчика. Проще всего это можно сделать, занося каждое
имя, содержащееся в записях-определениях, в таблицу внеш-
них имен (ESTAB) еще до того, как оно будет фактически
определено. Такие элементы таблицы помечаются специальным
маркером, показывающим, что данное внешнее имя еще не
определено. Когда встретится определение имени, то соответ-
ствующий ему адрес заносится в таблицу и имя становится
полностью определенным. В конце первого просмотра все не-
определенные имена, оставшиеся в ESTAB, представляю! сооо.ч
неразрешенные внешние ссылки. Для их разрешения загрузи \
должен просмотреть все заданные библиотеки и О1)Р1'|>() ‘ ’
найденные в них подпрограммы точно так же, как если
являлись частью входного потока. очеведь,
Заметим, что библиотечные подпрограммы диотеках
могут иметь внешние ссылки. Поэтому поиск в«“еках
надо проводить до тех пор, пока не будут разрешены ста.
внешние ссылки (или пока дальнейшее ра | а в библ ноте-
нет невозможным). Если после завер То их следует
ках останутся неразрешенные внешни >
рассматривать какошибки. „„«««.иит замещать стан-
Описанный процесс позволяет пр I < 1 м({ собственными
дартиые библиотечные подпрограммы своими
iin inpoi раммами. Предположим, например, что главная про-
грамма ссылается на стандартную подпрограмму SQRT Обыч-
но подпрограмма с этим именем выбирается из библиотеки и
подключается автоматически. Если программист по каким-то
захочет ^пользовать другую версию подпро-
1 рам мы SORI, то он может просто включить ее во входной
ПОТ?^г>4.°£ле завеРшения первого просмотра загрузчика ссылка
на 1 будет определена, и поэтому ее не потребуется искать
в библиотеках.
Загрузчик обычно работает с библиотеками, которые содер-
жат ассемблированные или откомпилированные версии подпро-
грамм (т. е. объектные программы). Просмотр библиотек мож-
но осуществлять с помощью сканирования записей-определений
всех объектных программ библиотеки, но это крайне неэффек-
тивно. Обычно для библиотек используется специальная файло-
вая структура. Она содержит каталог (директорий), в кото-
ром перечислены имена всех подпрограмм и имеются указатели
на их месторасположения в файле. Если подпрограмма до-
пускает вызов по нескольким именам (используя различные
входные точки), то все ее альтернативные имена также присут-
ствуют в каталоге. Конечно, сама объектная программа хра-
нится в единственном экземпляре, а все альтернативные имена
указывают на одну и ту же копию программы. Таким образом,
фактически библиотечный поиск сводится к просмотру каталога
и последующему чтению найденной объектной программы. Не-
которые операционные системы могут постоянно хранить ката-
логи наиболее часто используемых библиотек в оперативной
памяти. Это позволяет ускорить процесс поиска, если требуется
обработать большое количество внешних ссылок.
Мы рассмотрели библиотечный поиск применительно к раз-
решению ссылок на подпрограммы. Очевидно, что те же тех-
нические приемы могут быть одинаково хорошо применимы для
разрешения любых других типов внешних ссылок.
3.3.2. Управление процессом загрузки
Многие загрузчики допускают задание управляющих пар-
метров, которые позволяют изменять стандартный прощу-
описанный в разд. 3.2. В этом разделе мы остановимся ни -
которых типичных вариантах управления работой загрузчик- у
рассмотрим примеры их использования. Для задания унраь.» •'
щих параметров многие загрузчики используют специал>>
командный язык. Иногда для задания предложений ком и и >
го языка используется отдельный входной файл. В других
чаях эти предложения могут вставляться в основной вхо .
поток между объектными программами. Отдельные сщ'у
даже позволяют включать команды управления загрузчик*»'
исходную программу, а ассемблер или компилятор „
их в объектную программу. «-«мпилятор переносит
В этом разделе мы будем считать, что папамртпкл
ющие работой загрузчика, задаются с помХю₽™«»РаВЛЯ'
языка, хотя существуют и другие способы их мин»Т"0"1
торых системах команды управления загрузчиком являютеяТ
ставной частью языка управления заданиями, и поэтому „„й
обрабатываются операционной системой. В этом сл^ХУ
рационная система собирает все параметры в управляющий
блок, который становится доступным загрузчику после начала
его работы. Собственно реализация тех или иных возможностей
предоставляемых загрузчиком, конечно, остается той же самой
за исключением самих средств задания управляющих парамет-
Одной из типичных возможностей, предоставляемых пользо-
вателю, является определение альтернативного источника вход-
ного потока. Например, команда
INCLUDE имя-программы(имя-библиотеки)
может предписывать загрузчику прочитать определенную про-
грамму из библиотеки и работать с ней так, как если бы она
входила в состав исходного входного потока загрузчика.
Другие команды дают пользователю возможность исключить
некоторые внешние имена или целые управляющие секции. Кро-
ме того, может разрешаться изменять внешние ссылки во вре-
мя загрузки и связывания программ. Например, команда
DELETE имя-секции
может предписывать загрузчику исключить из рассмотрения
указанную управляющую секцию входного потока, а команда
CHANGE имя1,имя2
может использоваться для замены внешнего имени имя! па
имя2. Ниже приводится пример использования этих ко. д.
Рассмотрим исходную программу, изображенную на рпс. 2.10,
II соответствующую ей объектную пР°Ч^,мя> ИСПОЛРьзует две
Имеется главная программа (СОР»)> \ программ оформ-
подлрограммы (RDREC и WRREC). Есл^
лена в виде отдельной управляющемния в программе
WRREC разработаны только дляi испол ляюЩИ^ секции
COPY, то весьма вероятно, что все тр I означает> чт0 все
будут ассемблироваться °-JH0B^c положены в одном файле
три управляющие секции буду I библиотеку).
(или будут включены в одну СИСТе Ж*
Предположим теперь, в вычислите r£AD „WRITE
ся набор сервисных подпрогр • самых функции,
предназначены для выполнения тех
RDREC и WRREC. Вероятно, желательно будет изменить ис-
ходную программу COPY так, чтобы она могла использовать
эти сервисные подпрограммы. В качестве временной меры мож-
но использовать последовательность команд загрузчика, кото-
рые позволяют сделать эти изменения без переассемблирования
программы. Например, это может быть полезно для того, что-
бы протестировать сервисные подпрограммы прежде, чем де-
лать окончательное преобразование COPY.
Предположим, что в файл, в котором содержатся объектные
программы, показанные на рис. 2.17, включены дополнительно
следующие команды загрузчика:
INCLUDE
INCLUDE
DELETE
CHANGE
CHANGE
READ(UTLIB)
WRITE(UTLIB)
RDREC,WRREC
RDREC,READ
WRREC,WRITE
Эти команды предписывают загрузчику включить в рассмотре-
ние управляющие секции READ и WRITE из библиотеки UTL1B
и исключить из рассмотрения управляющие секции RDREC и
WRREC. Первая команда CHANGE служит для замены всех
ссылок к RDREC на READ. Аналогично ссылки к WRREC
заменяются на WRITE. Результат будет в точности таким, как
если бы исходная программа COPY была модифицирована для
использования READ и WRITE. Вам предлагается самостоя-
тельно подумать над тем, как загрузчик может осуществить об-
работку команд, обеспечивающих описанные действия.
Другая общеупотребительная возможность, предоставляе-
мая загрузчиком, касается автоматического библиотечного поис-
ка (как это было описано в предыдущем разделе). Большинство
загрузчиков разрешает пользователю задавать дополнительные
библиотеки с помощью команд типа
LIBRARY MYLIB
Такие пользовательские библиотеки обычно просматриваются
раньше стандартных системных библиотек, что позволяет ис-
пользовать в программе специальные версии стандартных под-
программ.
Загрузчики, выполняющие для разрешения внешних ссы 1
автоматический библиотечный поиск, часто дают пользован
возможность указать, что некоторые ссылки надо оставить
разрешенными. Предположим, например, что основной "
ей некоторой программы являются сбор и запоминание дан11 '
Кроме того, с помощью подпрограмм STDDEV, PL(
CORREL, которые расположены в библиотеке математпчи
статистики, она может проводить анализ данных. Пользован.^
может потребовать проведение такого анализа в пр»'>.•
149
выполнения Программы Посипит их/
на эти подпрограммы, то в об^ем с^ча7 он^были б"ЫЛК”
гружены в оперативную память и связаны с главной поогпзм'
мои. Если известно, что в данном конкретном запуске п 2
мы выполнение статистического анализа нс потпоГшптс Р
пользователь может включить в свое задание команду пщ а
NOCALL STDDEV.PLOT.XORREL
которая предписывает загрузчику оставить соответствующие
внешние ссылки неразрешенными. Это позволяет избежать на-
кладных расходов на загрузку и связывание ненужных подпро-
грамм и экономит место в оперативной памяти.
Кроме того, пользователь может вообще отказаться от ав-
томатического библиотечного поиска. Естественно, что если во
время исполнения прогрзмма попытэется воспользоваться не-
разрешенными ссылками» то это приведет к ошибке. Данный
режим бывает полезен тогда, когда требуется осуществить
только связывание программы без ее немедленного выполнения.
'В этом случае часто бывает желательно отложить разрешение
внешних ссылок на более позднее время. В разд. 3.4.1 мы рас-
смотрим редактор внешних связей, который выполняет эту
функцию.
Другим общеупотребительным средством является управле-
ние информацией, выводимой загрузчиком на печать.
В разд. 3.2.3 мы привели пример таблицы загрузки, которая
может создаваться в процессе работы загрузчика. С помощью
команд пользователь может указать, нужна ему распечатка
данной таблицы или нет. Если таблица нужна, то можно ука-
зать уровень ее детализации. Например, таблица может вклю-
чать только имена управляющих секций и назначенные им ад-
реса. Кроме того, она может включать адреса всех внешних
имен и даже таблицу перекрестных ссылок, в которой показа-
ны все ссылки на каждое внешнее имя.
Очень часто загрузчики предоставляют и другие дополни-
Одна из них — определение стартовой
тельные возможности. — ----- .
точки программы (она заменяет люоую информацию 1 пя?ое.
вой точке, заданную в объектной программе). ДР> ппоцес-
шение или запрещение выполнения программы, • неРазре.
се ее загрузки были обнаружены ошибки (например, 1
шенные внешние ссылки).
3.3.3. Оверлейная структура программ
В разд. 2.4.1 мы обсуждали реализацию дре-
ассемблера с простой оверлейной о’бъем оперативной
ализации позволяет сократить СУ Р ’ ак как для первого
памяти, требуемой для ассемблирования, так
которую мы
н второго просмотров используется одно и то же пространство.
В этом разделе мы рассмотрим более сложный пример и об-
судим, как осуществляется управление самим оверлейным про-
цессом. В качестве введения в данную тему вам следует об-
ратиться к рис. 2.18 и 2.19 и материалу разд. 2.4.1.
На рис. 3.12а показана программа с оверлейной структурой,
---ПРУ,Г' будем использовать в качестве примера. Буквами
_ - - -
обозначены имена управ-
ляющих секций, а линия-
а
управляющая
секция
А
В
С
D
Е
F
G
Н
1
Длина (в байтах)
1000
1800
4000
2800
800
1000
400
800
1000
800
2000
Рис. 3.12. Пример оверлейной программы.
к
6
ми — связи между ними
по передаче управления.
Таким образом, корневая
управляющая секция (со-
ответствующая ведущей
подпрограмме на рис.
2.18) имеет имя А. Уп-
равляющая секция А мо-
жет вызывать секции В,
С или D/Е; секция В мо-
жет вызывать F/G или
Н и т. д. Обозначение
D/Е используется для
спецификации двух уп-
равляющих секций (D и
Е), которые тесно связа-
ны между собой и всегда
используются совместно.
Хотя эти управляющие
секции раздельно обра-
батываются ассемблером
и загрузчиком, однако в
оверлейной структуре они
рассматриваются как
одно целое. Например, и
может содержать ncno.i-
— связанные с ними данные.
Другой пример Д- Е мспрт КЭК Е ~ связаниые с ними данные,
подпрограммы. На ри/з* 19содержать часто используемые в D
ричном виде) каждой vnno 2В показана длина (в шестнадцатс-
Большинство систем правляю^й секции.
мы, требует чтоб и ’ Одлерживающих оверлейные програм
кую, как на рис 3 12я? v,™ Древов"лнУ'" структуру (т. о. та-
ментами. Копневой mJ' ,узлы такого дерева называются си-
нения программы и ост!>1Т загрУжается в самом начале испол-,
Остальные сегменты чягп СТСЯ В памятн ло окончания счета
лит обращение. Ппелпо^^?.Ю1СА_Т0Гда’ когда к ним происхо-
ЦИЯ Д вызывает В?П%Л°ЖИМ' например, что управляющая сею
от вызов приведет к автоматической
загрузке сегмента, содержащего В (если только он ..
дится в оперативной памяти). Если позднее Л в^зовет^^т'
будет загружен сегмент, содержащий секцию D. П £к
положения сегментов, находящихся на одном уровне овеоК'
нои структуры, значения не имеет. Например, Л может снЛХ
вызвать С, затем В, затем D/Е, потом вновь С и т д
Предположим, что в некоторый момент времени’исполняется
управляющая секция Н. Она была вызвана секцией В котовую
в свою очередь вызвала секция А. Таким образом ’ эти тпи
сегмента являются активными и должны находиться в опера-
тивной памяти. Другие сегменты не могут быть активными
поскольку нет путей, связывающих их с Н. Например если ра-
нее был вызван сегмент, содержащий К, то он должен был
вернуть управление D/Е (и затем А) прежде, чем В мог быть
вызван из секции А. Данные рассуждения приводят нас к пра-
вилу, которое используется в большинстве систем, допускаю-
щих оверлейные структуры: если сегмент S находится в опера-
тивной памяти, то все другие сегменты, расположенные на
пути, ведущем из S к корню, также должны находиться в опе-
ративной памяти. Соблюдение этого правила упрощает органи-
зацию оверлея. Если некоторый сегмент вызывает сегмент, рас-
положенный на более низком уровне древовидной структуры
(т. е. находящийся дальше от корня), то может потребоваться
загрузка этого сегмента в оперативную память. С другой сто-
роны, если некоторый сегмент ссылается на сегмент,
лежащий
в памяти.
между ним и корнем, то этот сегмент уже находится
Поскольку сегменты одного уровня (например, В, С и D/E)
уровня,то
совместно
могут вызываться только из сегмента вышестоящего
они не требуются одновременно. Поэтому они могут
использовать одну и ту же область оперативной памяти. Если
передача управления вызывает загрузку ^некоторого ссгмеша,
то он замещает в памяти сегмент, который находится на одном
с ним уровне (и сегменты ему подчиненные). Таким образом,
общий объем оперативной памяти, требуемой для исполнения
программы, оказывается меньше. Это и является основной при
чиной использования оверлейных структур. ппмптии
Оверлейная структура программы описываетсяали в
команд загрузчика, похожих на те, что мы Р 1 ‘ анд к0.
предыдущем разделе. На рис. 3.13 пР"веденизобр^женНуЮ ’ на
торый задает оверлейную структур),
рис. 3.12а. Команда
SEGMENT имя-сегмента (управляющая-секция...)
определяет сегмент (т. е. узел дРевовИ^в Список входящих в
команда задает имя «гмента и описывает ^пис^,^
него управляющих секции. £ предложения SEGMEM
это корень. Два последовательных пред.
задают между описываемыми сегментами отношение вида отец —
сын. Поэтому на рис. 3.13 первые три предложения описывают
самый левый путь (от корня к F/G) структуры на рис. 3.12а.
Остальные сегменты, имеющие общего отца, на рис. 3.13
задаются с помощью предложений другого типа. Предложение
PARENT имя-сегмента
описывает сегмент (ранее определенный), который является от-
ним сегме-.та. Таким образом, на рис. 3.13
первое предложение PARENT определя-
ет, что SEG2 является отцом SEG4. Если
бы этого предложения не было, то от-
цом SEG4 считался бы сегмент SEG3.
Вам надлежит тщательно изучить
цом следующего за
SEGMENT
SEGMENT
SEGMENT
PARENT
SEGMENT
PARENT
SEGMENT
PARENT
SEGMENT
SEGMENT
PARENT
SEGMENT
PARENT
SEGMENT
SEG1(A)
SEG2(В)
SEG3(F,G)
SEG2
,SEG4(H)
SEG1
SEG5(C)
SEG1
SEG6(D,E)
SEG7(I)
SEG6
SEG8(J)
SEG6
SEG9(K)
Рис. 3.13.
оверлейной
помощью
предложений.
Определения
структуры с
управляющих
остальные определения и убедиться, что
они действительно описывают дре-
вовидную структуру, изображенную па
рис. 3.12а.
После того, как мы задали оверлей-
ную структуру, определение начальных
адресов сегментов становится простым
делом, так как каждый сегмент начина-
ется сразу после своего отца. Правило,
управляющее размещением сегментов в
оперативной памяти, обеспечивает раз-
мещение всех загруженных на данный
момент сегментов в областях, смежных
с областью, выделенной заданию в нача-
ле его работы. На рис. 3.14а показаны
длина и относительный адрес начала
каждого сегмента рассматриваемой на-
ми программы. На этом же рисунке показаны фактические,
начальные адреса (считается, что начальный адрес загрузки
равен 8000). Во время выполнения программы в памяти мшу
присутствовать различные наборы сегментов. На рис. 3.146 по-
казаны три возможных варианта. С остальными вам предлаы-
ется разобраться самостоятельно. Позднее мы увидим, что
грузчик может добавить одну или несколько специальны^ '
равляющих секций, содержащих информацию для управу-
оверлейной структурой. Естественно, что длина этих секи
должна учитываться при назначении адресов. Klli'i
Как мы видели, загрузчик может назначить факт '..1с
адрес загрузки каждому сегменту оверлейной структуры
того, как будет определен начальный адрес. Таким оОР‘’.и>Г1
становятся известны адреса всех внешних имен. Это 03,1‘ ' 1Ь.
что все операции перемещения и связывания могут в1’|||031),ьС11
ся обычным образом, но с одним исключением
иметь возможность пеоелатк
этот момент нс находится в оперативиоГиамяти"^’ КОТОРЫЙ »
левого сегмента может производиться и₽п^ ' 3агРУзка кор-
тнвную память. Остальные сегменты (для которые”"0 ° °Пе|>’’
иены операции перемещения в связ^ва’ннТз^ыТа^еГв
специальный файл (SEC-
TILE), создаваемый за-
грузчиком.
Собственно оверлей-
ный процесс (т. е. загруз-
ка сегмента, когда ему
передается управление)
может осуществляться
различными способами.
Здесь мы опишем простой
механизм, который не
требует вмешательства
операционной системы.
Наряду с ним могут ис-
Сегмент
Началы1Ъ1Й адрес
Длина
Относительный ческйй
1 0000 8000 1000
2 1000 9000 1800
3 2800 А800 1400
4 2800 А800 800
5 1000 9000 4000
6 1000 9000 3000
7 4000 СООО 1000
8 4000 СООО 8С0
9 4000 СООО 2000
пользоваться средства,
аналогичные аппарату
динамического связыва-
ния (см. разд. 3.4.2).
Фактическая загрузка
сегментов в процессе ис-
полнения программы осу-
ществляется специальной
программой — менедже-
ром оверлея (overlay ma-
nager). В нашем приме-
ре менеджер оверлея
расположен в отдельной
управляющей секции с
именем OVLMGR. Эта
секция автоматически
«
8000
$000
А000
вооо
сооо
D000
ЕОО0
«
6
Рис. 3.14. Распределение памяти для овср
лейной программы.
включается загрузчиком
в корневой сегмент оверлейной программы. Для управления за
грузкой сегментов OVLMGR должен иметь информацию> <
оверлейной структуре программы. Эта информация хр>
таблице сегментов (SEGTAB), которая создаете<Р;авляю-
и включается в корневой сегмент в виде отдеструк-
Щей секции. Таблица SEGTAB описывает древов
туру, определяя уровень расположения начальный ад-
Для каждого сегмента она также содерж оложенИе сег-
рес загрузки, адрес входной точки и мес™р*сп™лагаем, что
мента в SEGF1LE. (В данной реализацш"°0^ т0ЧКс.)
сегмент может вызываться только по од
Кроме того, для каждого сегмента, за исключением корня
в SEGTAB, имеется область передачи управления. Опа содер-
жит команды, которые обеспечивают передачу управления па
требуемый сегмент. Если сегмент уже загружен в оперативную
память, то его область передачи управления содержит простую
команду перехода на входную точку сегмента. Если сегмент не
загружен, то область передачи управления содержит команды
активизации OVLMGR и передачи ему информации, необходи-
мой для загрузки сегмента. В процессе своей работы мене-
джер оверлея изменяет команды в области передачи управле-
ния так, чтобы они всегда соответствовали текущему статусу
каждого из сегментов. Обращение одного сегмента к другому
стоящему на следующем уровне древовидной структуры (т. е’
обращение, которое может потребовать оверлейную загрузку),
преобразуется загрузчиком в обращение к области передачи
управления соответствующего сегмента. Область передачи
управления всегда присутствует в оперативной памяти, так как
SEGTAB расположена в корневом сегменте. Затем команды
области передачи управления либо непосредственно передают
управление на требуемый сегмент, либо активизируют
OVLMGR. В последнем случае OVLMGR загружает требуемый
сегмент, обновляет SEGTAB и после этого передает управление
сегменту.
Иллюстрация описанного процесса дана на рис. 3.15. Па
рис. 3.156 показано содержимое оперативной памяти на неко-
тором этапе исполнения программы. В данный момент загру-
жены Сегменты 1, 2, 4 и исполняются команды управляющей
секции А. Сегменты 2 и 4 были загружены в ответ на ранее
выполненные команды вызова. Хотя сейчас управление верну-
лось Сегменту 1, однако Сегменты 2 и 4 продолжают оставать-
ся в оперативной памяти до тех пор, пока их не заменят дру-
гие сегменты. Области передачи управления Сегментов 2 и 4
содержат команды перехода на управляющие секции В и Н.
Остальные области передачи управления содержат команду
активизации OVLMGR (соответствующие им поля SEGTAB за-
штрихованы). Если в управляющей секции А сейчас будет вы-
полнена команда вызова секции В (в исходной програму
команда -}-JSUB В), то в результате выполнится переход
область передачи управления Сегмента 2. Как показано
рисунке, это приведет к прямой передачи управления на cei
пню В. .
Предположим теперь, что А вызывает D. На рис. 3.1о уф-
зано, что область передачи управления, соответствующая 1
менту 6, содержит команды активизации OVLMGR. Менедли
оверлея загрузит Сегмент 6 из SEGF1LE на выделенное у
место в оперативной памяти. Затем он обновит SEGTAB, '4
зав, что в данный момент Сегмент 6 находится в памяш,
OVLMGR
Н
е
9
Сегмеит^4
(SEG4)
Сегмент#2
(SEG2)
* SEGTA8
Корневой сегмент
(SEGI)
+JSU0 В
• OVLMGR
г
I 1 j
Корневой сегвдиг
' (SEGI)
Сегмент 46
' (SEG6)
Рис. 3.15. Пример управления
оверлеем.
Сегменты 2 и 4 нет. Заметим, что
Сегмент 4 должен быть удален из
памяти (даже если занятое им про-
странство не требуется для ново-
го сегмента), так как удален его
отец. Теперь для вызова секции D
остается передать управление на
входную точку Сегмента 6 (см.
рис. 3.15в).
Возврат управления из вызван-
ного сегмента (например, из D в
А) может выполняться обычным
образом. (Активизация OVLMGR
для этого не требуется.) Например,
команда JSUB (рис. 3.156) может
занести адрес возврата в регистр
L. Менеджер оверлея сохранит это
значение. Таким образом, по за-
вершению своей работы управляю-
щая секция D может просто вы-
полнить команду RSUB. Это тот
же самый механизм, который ис-
пользуется для программ без овер-
лейной структуры.
В некоторых системах функции OVLMGR выполняются спе-
циальным блоком операционной системы, который называется
супервизором оверлея (overlay supervisor). В этом случае
SEGTAB содержит макрокоманды операционной системы, обес-
печивающие загрузку требуемого сегмента.
3.4. Варианты построения загрузчиков
В данном разделе мы рассмотрим некоторые общие вариан-
ты реализации функций загрузчика, включая перемещение и
связывание. Связывающие загрузчики, рассмотренные в
разд. 3.2.3, выполняют связывание и перемещение в процессе
загрузки. Здесь мы обсудим две альтернативные схемы — ре-
дакторы связей, выполняющие связывание перед загрузкой, и
динамическое связывание, в котором функции связывания осу-
ществляются во время исполнения программы.
В разд. 3.4.1 рассматривается редактор связей, который во
многих вычислительных системах используется вместо связы-
вающего загрузчика или в качестве его дополнения. Редактор
связей осуществляет связывание и некоторые действия по пере-
мещению, однако подготовленная им программа загружается
не в оперативную память, а записывается в файл или в библи-
отеку. Этот подход позволяет сократить накладные расходы на
обработку программы, так как загрузчику остается выполнить
лишь очень простые операции настройки относительных ад-
ресов.
В разд. 3.4.2 мы познакомимся с механизмом динамического
связывания. В этой схеме загрузка программ осуществляется в
момент первого вызова, и для этого используются средства
операционной системы. Откладывая связывание до момента вы-
зова, мы можем получить дополнительную гибкость в организа-
ции программ. Однако обычно это ведет к дополнительным по
сравнению со связывающим загрузчиком накладным расходам.
В разд. 3.4.3 мы обсудим раскручивающие загрузчики (boot-
strap loaders). Такие загрузчики могут использоваться для про-
грамм, выполняемых без операционной системы или системного
загрузчика. Они также могут применяться для загрузки в опе-
ративную память самой операционной системы или системного
загрузчика.
3.4.1. Редакторы связей
Основное различие между редактором связей и связываю-
щим загрузчиком показано на рис. 3.16. Вначале исходный
текст переводится ассемблером или компилятором в объекта) ю
программу (которая может состоять из нескольких управляю-
щих секций). Связывающий загрузчик выполняет все операции
связывания и перемещения nwnmiro».
автоматический библиотечный поиск и VaVov^ao"606'4041^0’ ”
ную для исполнения программунепоепопеГРУ подготовлен-
память. С другой
PTJ с РазРешеннымн внешними «язями (его «
сто называют загрузочным модулем или исполняемо,I прога, м
мои) и записывает его в файл или в библиотеку "Рограм-
Рис. 3.16. Обработка объектной программы с использованием связывающего
загрузчика (а) и редактора связей (б).
аей^ЛЯ загРУзки программы, подготовленной редактором свя-
ч ’ р0?кет быть использован простой перемещающий загруз»
вс₽м МУ остается только прибавить адрес начала загрузки ко
зей относительным адресам внутри программы. Редактор сия-
т выполняет размещение всех управляющих секций относи»
мо ЬН|? начала программы. Таким образом, все поля, требующие
одификации во время загрузки, получают значения относи-
сльно начала программы. Это означает, что загрузка может
Ыполняться за один просмотр без использования таблицы
®нещних ссылок. По сравнению со связывающим загрузчиком
’акая загрузка требует намного меньших накладных расходов,
-ели программа должна выполняться много раз без переас-
ссмблирования, то использование редактора связей позволяет
существенно снизить затраты на разрешение внешних связей и
библиотечный поиск, так как они в этом случае выполняются
только одни раз, в то время как связывающий загрузчик вы-
полняет их при каждом запуске программы.
Однако иногда программа переассемблируется практически
при каждом новом запуске. Такая ситуация характерна при
разработке и тестировании программ (например, обработка
студенческих заданий). Кроме того, если программа использует-
ся довольно редко, то может оказаться нецелесообразным хра-
нить ее ассемблированную версию в библиотеке. В этих слу-
чаях связывающий загрузчик является более эффективным, так
как он позволяет обойтись без операций записи и чтения за-
грузочного модуля.
Программа, создаваемая редактором связей, обычно записы-
вается в форме, удобной для ее обработки перемещающим за-
грузчиком. В ней разрешены все внешние связи, а информация
о перемещаемых адресах задается с помощью записей-модифи-
каторов или масок перемещения. Несмотря на то что все опе-
рации связывания уже выполнены, в загрузочном модуле часто
сохраняется информация о внешних ссылках. Это позволяет
впоследствии проводить в загрузочном модуле операции по за-
мене управляющих секций, изменению внешних связей и др.
Если такую информацию не сохранять, то последующая обра-
ботка загрузочного модуля с помощью редактора связей будет
невозможна. В этом случае единственное, что можно будет
делать с программой,— это загружать ее в память и ис-
полнять.
Если фактический адрес загрузки программы известен зара-
нее, то редактор связей может выполнить всю необходимую
настройку. В результате будет получено представление про-
граммы, которое в точности соответствует ее виду во время
исполнения. Такая программа ничем не отличается от абсолют-
ной объектной программы. Однако обычно возможность загру-
жать программу в любое место памяти вполне компенсирует тс
расходы, которые требуются для выполнения настройки отно-
сительных адресов во время загрузки программы.
Кроме подготовки объектной программы редактор связен
может выполнять и много других полезных функций. Рассмот-
рим, например, программу (PLANNER), которая используем
большое количество подпрограмм. Предположим, что в одну и >
этих подпрограмм (PROJECT) внесены изменения (например,
для исправления ошибок или повышения эффективности). И
еле ассемблирования или компилирования новой версии
PROJECT мы должны включить ее в PLANNER. Редактор свя-
зей позволяет сделать это, нс возвращаясь к исходным (раздел1'
ным) версиям всех программ. Ниже приведена последователь
иость команд редактора связей, которая позволяет выполним'
эту работу. Используемый здесь язык аналогичен тому, что m|J
рассматривали в разд. 3.3.2:
INCLUDE
DELETE
INCLUDE
REPLACE
PLANNER(PROGLIB)
PROJECT
PROJECT(NEWLIB)
PLANNER(PROGLIB)
{Исключить из старой
версии}
{Включить новую версию}
Редакторы связей могут также использоваться для поотпп
ния пакетов из подпрограмм или управляющих секций ЛЛР
щих совместного использования Такая ситг-япи^ ’ р бую'
для библиотек, обеспечивающих поддержи? язь1 *арактер,,а
уровня. Например, при реализации я/ы^Ф^рТрац бьХщ
пользуется большое количество подпрограмм/ выполняющих
форматный ввод-вывод. К ним относятся подпрограммы чтения
и записи олоков данных, блокирования и разблокирования запи-
сей, а также подпрограммы кодирования и декодирования ин-
формации в соответствии с заданными спецификациями опе-
ратора rORMAT. Так как эти подпрограммы тесно увязаны
между собой, то между ними имеется большое количество пе-
рекрестных ссылок. Вместе с тем для обеспечения модульности
и облегчения сопровождения подпрограмм желательно, чтобы
они были представлены в виде отдельных управляющих секций.
Если бы программа, использующая форматный ввод-вывод,
связывалась обычным образом, то все перекрестные ссылки
между библиотечными подпрограммами выполнялись бы раз-
дельно. Причем практически для любой Фортран-программы
набор этих перекрестных ссылок был бы одним и тем же.
Естественно, что это привело бы к значительным издержкам.
Редактор связей позволяет решить эту проблему путем объеди-
нения некоторых подпрограмм в единый пакет. Необходимую
для этого информацию можно задать, например, следующим
образом:
INCLUDE READR(FTNLIB)
INCLUDE WRITER(FTNLIB)
INCLUDE BLOCK(FTNLIB)
INCLUDE DEBLOCK(FTNLIB)
INCLUDE ENCODE(FTNLIB)
INCLUDE DECODE(FTNLIB)
SAVE
FTNIO(SUBLIB)
В каталоге библиотеки SUBLIB
загрузочный модуль FTNIO, присутствую . , ' SUBLIB
нами. Поэтому если просматривать I-TNIO, а не
раньше, чем FTNLIB, то будет найден модуль
отдельные подпрограммы. Поскольку в FTNIO все внешние
связи между подпрограммами уже разрешены, то, следователь-
но, они не будут обрабатываться при обработке пользователь-
ской программы. В результате повысится эффективность выпол-
нения операции связывания и будут значительно снижены сум-
марные затраты на работу системы.
Редакторы связей часто разрешают пользователю указывать
те внешние ссылки, которые не должны обрабатываться с по-
мощью автоматического библиотечного поиска. Предположим,
например, что в библиотеке должно храниться 100 Фортран-
программ, в которых используются описанные выше подпро-
граммы ввода-вывода. Если все эти программы хранить с пол-
ностью разрешенными внешними связями, то в библиотеке бу-
дет записано 100 копий FTNIO. Если библиотечное простран-
ство дорого, то это может оказаться крайне нежелательным.
В этом случае пользователь может с помощью команд, похожих
на те, что были рассмотрены в разд. 3.3.2, запретить выполне-
ние библиотечного поиска во время работы редактора связей.
Тогда будут разрешены только внешние связи между пользо-
вательскими подпрограммами. Впоследствии во время испол-
нения программы для объединения пользовательской програм-
мы с модулем FTNIO можно будет использовать связывающий
загрузчик. Поскольку в этом случае потребуется выполнить две
отдельные операции связывания, то это приведет к некоторому
увеличению накладных расходов, но зато позволит сэкономить
библиотечное пространство.
Редакторы связей часто обеспечивают выполнение и других
операций и команд, подобных тем, что мы рассматривали для
связывающих загрузчиков. По сравнению со связывающими за-
грузчиками редакторы связей в общем случае предоставляют
большую гибкость и разнообразие средств управления загруз-
кой. Однако за это приходится расплачиваться ростом сложно-
сти программного обеспечения и увеличением накладных рас
ходов.
3.4.2. Динамическое связывание
Редакторы связей выполняют операции связывания до тог1
как программа загружается для исполнения. Связывающий
грузчик выполняет эти же операции во время загрузки пр'
граммы. Здесь мы рассмотрим схему загрузки, в которой с
ываиие откладывается до момента исполнения программ
слУчае загрузка и связывание подпрограммы осущее
г/.- Т01да’ К0ГДа к пей происходит первое обращение. ।
ч/'скпм ,*о1.3аЦИЯ "1)Оцесса загрузки обычно называется дина'
грузкой [dynamic linking) или динамической
ерузкоа (dynamic loading).
По сравнению с ранее обсуждавшимися схемами обработки
внешних связей динамическое связывание имеет ряд преиму-
ществ. Предположим, к примеру, что программа содержит под-
программы, предназначенные для исправления или подроб-
ного диагностирования ошибок во входных данных. Если такие
ошибки редки, то в большинстве запусков программы эти под-
программы будут не нужны. Однако если программа полно-
стью связывается до начала исполнения, то эти подпрограммы
должны загружаться (и для них должны обрабатываться внеш-
ние связи) каждый раз, когда исполняется программа. Дина-
мическое связывание позволяет загружать подпрограммы в
том (и только в том) случае, когда они действительно нужны.
Если соответствующие программы занимают много места или
имеют много внешних связей, то это может дать существенную
экономию времени и пространства оперативной памяти.
Похожая ситуация возникает и тогда, когда при каждом
конкретном запуске программы используется лишь незначи-
тельная часть подпрограмм из большого числа потенциально
используемых. Причем, какие именно подпрограммы будут ис-
пользоваться, становится известно только после обработки
входного потока. Такая организация программы характерна,
например, для интерактивных систем, в которых пользователю
разрешается в процессе диалога вызывать различные библио-
течные подпрограммы. В этом случае входные данные вводят-
ся пользователем с клавиатуры, а полученные результаты
выводятся на экран терминала. В каждом сеансе работы поль-
зователь может потенциально обратиться к любой библиотеч-
ной подпрограмме, однако фактически используется лишь их
небольшая часть. Благодаря динамическому связыванию отпа-
дает необходимость загружать при каждом запуске все библио-
течные подпрограммы. Более того, динамическое связывание
позволяет главной программе вообще ничего не знать о том, с
каким набором подпрограмм она должна работать, так как
имена подпрограмм могут обрабатываться точно так же, как и
Другие входные данные.
Существуют различные механизмы, позволяющие осущест-
влять загрузку и связывание в момент вызова подпрограммы.
Здесь мы обсудим подход, при котором динамическое связыва-
ние осуществляется с помощью запросов к операционной систе-
Ме- При желании можно рассматривать эти запросы как обра-
щение к резидентной части загрузчика.
При динамическом связывании программа вместо того, чтс
бы выполнять команду JSUB, в которой используется внешнее
Имя, должна выполнить запрос к операционной cllclcMt 1 ‘о.‘а
гРузку и исполнение подпрограммы. Параметром эт0|()
является символическое имя требуемой n0^"Pv‘
iipHc. 3.17а), Операционная система по своим ) Р »
Зэгрузка-и- вызов
ERRHANDL
Динамичес-
кий загруз-
чик (блок
операционной
системы)
Программа
пользователя
Динамический
загрузчик
Программа
пользователя
ERRHANDL
Программа
пользователя
Динамический
загрузчик
ERRHANDL
Загрузка-и-вызов
ERRHANDL
Динамический
загрузчик
Программа
пользователя
ERRHANDL
в
Рис 3.17. Загрузка и
зывания.
вызов подпрограмм с помощью динамического свя-
п1?.иИ1гаМ опРеделяет> загружена ли данная подпрограмм;) ”
। „ М°М< 111 вРемеии или нет. Если это необходимо, то по;
Р р ма загружается из пользовательской иди системно)1
библиотеки (рис. 3.176). После этого опепяпнпИНЯО
вызывает требуемую подпрограмму (рис з 17% система
После завершения своей работы подпрограмма возвращает
управление в точку, откуда она была вызвана (т е сервисной
подпрограмме операционной системы, выполняющей динамч"
скую загрузку). Затем операционная система возвоашаЛ vn
равление программе, выдавшей запрос. Этот процесс показан
на рис. 3.17г. Очень важно, чтобы возврат из подпрограммы
осуществлялся через операционную систему, так как в этом
случае ей будет известен момент завершения вызванной под-
программы. После окончания работы подпрограммы занятая ей
оперативная память освобождается и может быть использована
для других целей. Однако это необязательно делать немедлен-
но. Иногда желательно сохранить подпрограмму в памяти для
последующего использования до тех пор, пока не потребуется
память для других процессов. Если подпрограмма все еще на-
ходится в памяти, то ее повторный вызов может осуществляться
без перезагрузки. В этом случае динамический загрузчик про-
сто может передать на нее управление, как это показано на
рис. 3.17д.
При динамическом связывании установление соответствия
между символическим именем вызываемой подпрограммы и
фактическим адресом ее загрузки не делается до тех пор, пока
не будет выполнена команда вызова. Другими словами можно
сказать, что привязка имени к фактическому адресу отклады-
вается до момента исполнения программы. Как мы уже гово-
рили, это дает нам большую гибкость в организации програм-
мы. В то же время это приводит к дополнительным накладным
расходам, так как операционная система должна участвовать в
процессе вызова подпрограмм. В последующих главах мы уви-
дим другие примеры, в которых используется откладывание
привязки. Как и в данном случае, такая отложенная привязка
дает большие возможности за дополнительную плату.
3.4.3. Раскручивающие загрузчики
В нашем обсуждении мы не затрагивали один в%' ’ 1ЯТЬ?
лрос: как сам загрузчик загружается в onep%% иионной си-
Конечно, можно сказать, что он загружается‘ операциОн-
стемой, но тогда возникает вопрос: кто < I - ссьормулиро-
»ую систему? В более общем виде вопрос а ' пустую ма-
кать так: каким образом можно запустить Р . пр0Граммы?
Шину, в оперативной памяти которой нет ти в перемен
В ситуации, когда машина “^’«"рое™ определить
Шенин программ не возникает. Мы Идй загрузки про-
произвольный абсолютный адрес пер•_ л.,дет операДионнаЯ!
Наиболее часто этой программой Суды
П>аммы.
система, которая занимает заранее определенное место в памя-
тн. Это означает, что нам нужны некоторые средства тля вы-
волнения функции абсолютного загрузчика. Одно из возможных
решении - поручить оператору ввести в оперативную память
объектный код абсолютного загрузчика с помощью пеоеключа
телей на пульте ЭВМ. Некоторые машины требуют именно До
Однако такая процедура слишком неудобна и не застрахована
от ошибок, чтобы быть действительно хорошим решением тан
пой проблемы.
Другое решение иметь программу абсолютного загрузчика
в качестве резидента, записанного в память, доступную только
для чтения (постоянное запоминающее устройство — ПЗУ) Ко-
гда возникает некоторый аппаратный сигнал (например, опера-
тор нажимает кнопку «старт системы»), машина начинает вы-
полнять программу, записанную в ПЗУ. В некоторых машинах
программа исполняется непосредственно в ПЗУ, в других —она
копируется в основную память и исполняется в пей. Однако не
все машины имеют ПЗУ. Кроме того, использование ПЗУ за-
трудняет модификацию абсолютного загрузчика, если в этом
возникает необходимость.
Промежуточное решение заключается в том, чтобы иметь
встроенные аппаратные средства (или очень короткую програм-
му в ПЗУ), которые позволяют прочитать запись фиксирован-
ной длины с некоторого внешнего запоминающего устройства в
фиксированное место оперативной памяти. Используемое кон-
кретное устройство обычно можно задать с помощью пультовых
переключателей. После того как запись будет прочитана в па-
мять, управление передается на ее начало. Считанная запись
содержит команды загрузки абсолютного загрузчика. Если
команды, требуемые для организации процесса загрузки, не по-
мещаются в одну запись, то первая запись может служить для
чтения еще одной записи, а та в свою очередь может прочшаin
еще и другие записи. Первая запись (или записи) обычно на-
зывается раскручивающим загрузчиком (bootstrap loader). 1j-
кие загрузчики должны находиться в начале любой объем ш
программы, которая предназначена для работы на пустой
шине. К числу таких программ относятся, например, сами
рационные системы и все другие программы, которые должь->
выполняться без операционной системы.
3.5. Примеры реализации
В данном разделе мы кратко познакомимся с
। н с -
связей и загрузчиками для реальных машин. Поскольку И 1
ляция и загрузка взаимосвязаны, мы в качестве примеров
дем использовать те же самые три машины, что и в разд
165
При чтении данного пя^л»по
пням машин, которыеРбыли даньГв “Т’ °бращатьс>’ к описа-
Как и ранее, мы не ставим перет. собой
описание рассматриваемых редакторов свяЛ ’ ДЗТЬ ПОЛНос
Вместо этого особое внимание будет удел₽нл " загРУзчиков.
росным иди необычным возможностям и о• lTbI,UM ИНТе’
лизании от общей модели, рассмотренной мм п ДпНИЫХ реа'
разделе. Мы также укажем на те гппй?! предыдущем
и загрузчиков, которые обусловлены особенна?™акторов связеГ1
или структуры ЭВМ. ’ Ценностями ассемблеров
3.5.1. Редактор связей System/370
Формат объектной программы, обрабатываемой редактором
связей System/370, очень похож на тот, что мы обсуждали в
связи с УУМ/ДС. Для повышения эффективности используется
механизм ссылочных номеров, рассмотренный нами в разд. 3.2.3.
Выходная программа редактора связей называется загрузочным
модулем (load module). Загрузочные модули могут загружать-
ся в оперативную память и исполняться. Они также (обычно)
содержат информацию, необходимую для их последующей об-
работки с помощью редактора связей. Однако пользователь
может указать, что некоторый модуль является «нередактируе-
мым», и в этом случае большая часть управляющей информа-
ции будет опущена. Это позволяет делать более компактные
загрузочные модули.
Редактор связей System/370 может выполнять все обсуждав-
шиеся нами стандартные операции. Управляющие секции мож-
но исключать, заменять или реорганизовывать. Имена, исполь-
зуемые во внешних ссылках, можно заменять или исключать.
Для облегчения редактирования обеспечивается автоматическая
замена управляющих секций. Если две или более обрабатывае-
мые управляющие секции имеют одинаковые имена, го только
первая из них будет включена в загрузочный модулы Др\из-
будут исключены, и это не рассматривается как оши >ка. , •
обработки внешних ссылок редактор связей выполняет < _
тический библиотечный поиск в системных и поль j <
библиотеках. Однако пользователь может залр (<
иск для некоторых или даже для всех BHCLIJII"O ’ разиообраз-
Редактор связей хранит в загрузочном модуле 1,^^ ! цз
ную информацию, в том числе, да У I гося транслятора,
объектной программы) и тип испольДВ,^щи (что позволяет
а также даты редактирования и мош J,,). Когда ре-
иметь историю работы с за! РУ3041; л в библиотеку, то
дактор связей помещает загрузочн > )ге о каждом moi\ '1
он заносит его имя в каталог. _ информация, напри*'1 >
•роме имени хранится и Д1 -
допускаем ли модуль повторную обработку редактором связей,
имеет ли он оверлейную структуру, является ли он повторно вхо-
димым или разделяемым и многие другие атрибуты. Некото-
рые из этих атрибутов сообщаются пользователем, другие гене-
рируются редактором связей в процессе работы.
Редактор связен System/370 поддерживает оверлейные поо-
граммы, структура которых совпадает с той, что мы рассмат-
ривали в разд. 3.3.3, и даже предоставляет более широкие воз-
можности. В каждом сегменте разрешается использовать не-
сколько входных точек. Для этого в каждый сегмент, который
может потребовать оверлейную загрузку, автоматически вклю-
чается таблица входов {entry table). В этой таблице для каж-
дого внешнего имени указан соответствующий ему сегмент
Имеется также и таблица сегментов (она похожа на таблицу
сегментов, описанную нами в разд. 3.3.3). В оверлейных про-
граммах при некоторых ограничениях разрешено использовать
так называемые исключительные ссылки {exclusive referen-
ces)— ссылки, которые требуют оверлейного замещения самого
вызывающего сегмента. Примером такой ссылки мог бы слу-
жить вызов сегмента С из сегмента В в программе на
рис. 3.12а. Однако пользоваться этой возможностью рекомен-
дуется только в особых случаях. В стандартном режиме (если
не задан соответствующий атрибут) такие ссылки рассматри-
ваются редактором связей как ошибочные.
Как уже говорилось в разд. 3.3.3, оверлейная загрузка осу-
ществляется автоматически при вызове сегмента. Кроме того,
программа может явным образом потребовать загрузку конкрет-
ного сегмента (обратившись к операционной системе). Некото-
рые версии операционной системы допускают продолжение
исполнения сегмента, выдавшего запрос, в то время как про-
изводится загрузка требуемого сегмента. Это позволяет совме-
щать во времени процессы загрузки и исполнения программы.
Естественно, что подобные параллельные операции необходимо
тщательно планировать при проектировании оверлейной про-
граммы.
В System/370 оверлейные программы могут разбиваться на
несколько различных областей, что позволяет более эффектив-
но использовать оперативную память. Каждая область содер-
жит древовидную оверлейную структуру. Внутри одной облает
применяются обычные правила организации оверлея. Однам'
области не зависят друг от друга, и поэтому сегмент однон
области может свободно обращаться к любому сегменту др}г0,1
области.
Рассмотрим, например, структуру на рис. 3.18а. Это та
самая оверлейная структура, что и на рис. 3.12а, но с доо.^
ленными управляющими секциями L, М и N. Каждая из
может вызываться либо из секции Н, либо из секции <1. г
Рис. 3 18. Оверлейная программа, расположенная
в нескольких областях»
структура является недопустимой, так как L, М и N размеще-
ны в двух различных узлах дерева, что приводит к неоднознач-
ному определению внешних имен. Для того чтобы организовать
допустимую оверлейную структуру, расположенную в отпой
области, нам надо было бы разместить L, М и N в копневом
сегменте. В этом случае они были бы доступны как И так и
J (рис. 3.186). Однако это означало бы, что" все эти три’управ
ляющие секции оставались бы в оперативной памяти в течение
всего времени исполнения программы. Таким образом преиму-
щество оверлейной структуры было бы утрачено Если L М
и N велики по объему, то это привело бы к значительному
увеличению размера занимаемой оперативной памяти. 7
На рис. 3.18в эта проблема решена с помощью размеще-
ния оверлейной структуры в нескольких областях. Область 1
содержит ту же самую оверлейную структуру, которая приве-
дена на рис. 3.12а. Область 2 содержит сегменты L, М и N.
Эти сегменты подключены к фиктивному корню для того, что-
бы подчеркнуть, что они могут друг друга замещать. Это по-
зволяет решить проблему эффективного использования опера-
тивной памяти и в то же время позволяет обращаться к
любому сегменту Области 2 как из сегмента Н, так и из сег-
мента J.
Обычно в состав System/370 наряду с редактором связей
входит и связывающий загрузчик. Загрузчик предоставляет
меньше средств, чем редактор связей. Например, он нс поддер-
живает оверлейные программы и не создает загрузочные моду-
ли, которые можно помещать в библиотеку. Однако, поскольку
загрузчик является более простым и не создает загрузочные
модули, он позволяет сократить примерно на половину время,
требуемое на загрузку и связывание программы. Поэтому для
повышения эффективности его рекомендуется применять всегда,
когда не требуется выполнять специализированные функции
редактора связей.
Более подробную информацию о редакторе связей 8у-
ster?i/370 можно найти в IBM [1978] и IBM [1972а].
3.5.2. Программа связывания ЭВМ VAX
Редактор связей в системе VAX называется программ
связывания (linker) и выполняет функции, аналогичные тем, ч!"
мы уже обсуждали в этой главе. Формат объектной програм-
мы VAX несколько более сложный, чем формат, использов.н -
шийся для УУМ/ДС. Результатом работы программы связывч-
ния является одна или несколько блок-секций (image section
Блок-секция состоит из нескольких программных сект
(PSECT), имеющих сходные значения атрибутов (например,
таких как защита по записи или исполнению),
р _
Работа программы связывай ~ ~--------—
управляется ассемблером или изданию блок-сок.,, -
Ьльных команд, включаемых в объёкт7у°ю°п С ПОМОЩЬ1« спёХ,-
модификатор, являющаяся частив прогРаммУ. (Запись,
уУМ/ДС, представляет ЭсоСбой “простой примТп °и прогр"ммы
типа.) В качестве рабочей памяти прогимм? ома"лы этого
пользует внутренний стек. Команды объетн.й связыва"«я „с-
гут заносить в стек разнообразную нпфопмУ ^граммы «»
значения из стека и записывать их в блок™ё!Ю1 'ЧИ™Вать
поднять операции над величинами, записанный ’ также ВЬ1'
команд состоит более чем из 50 различи ё ,- В стек- Наб(,Р
чнваюших самые широкие возможности операцпи, обеспс-
На рис. 3.19 приведен простой примео
лый способ организации перемещения ™РИРУЮЩ11Йдаи‘
рнс. 3.19а показаны три программныесекши, ассемб?^ На
шиеся совместно. По существу это те же nnnr'n сСсмблнРовав-
которые использовались нами в примере на рис “ST О™’
здесь показана только та часть, которая необходима для обо?
ботки предложения с меткой REF4 (из секции PROGA)’
На рис. 3.196 приведен несколько упрощенный вариант
команд, обеспечивающих генерацию значения предложения
Первая команда заносит в вершину стека число 14 (шест-
надцатеричное), являющееся значением выражения (ENDA —
LISTA). Вторая команда заносит в стек базовый адрес сек-
ции PROGC (он назначается программой связывания) плюс
смещение 30 (шестнадцатеричное). Эта сумма представляет
собой значение метки LISTC. Третья команда суммирует два
верхних элемента стека и помещает результат в его вершину.
Последняя команда запоминает эту величину в качестве сле-
дующего слова генерируемой блок-секции. Это как раз то зна-
чение, которое должно содержаться в слове с меткой REF4.
Программа связывания VAX может генерировать три типа
блок-секций. Блок-секции первого типа — это выполняемые сек-
ции {executable images), используемые для загрузки и исполне-
ния. Однако их последующая обработка программой связыв-
ая невозможна. Второй тип блок-секций — это разделяемые
$&Щии {shareable images). Такие секции исполняться не могут,
но зато они могут впоследствии обрабатываться программой
связывания. Их можно, например, использовать в качестве^про-
межуточного представления для очень больших ПР р '
Разделяемые блок-секции позволяют также.р Ропого на-
^Рограммам использовать одну и ту же копию i Р^ в
Фа команд или областей данных. На маг” чкземПляр раз-
°перативиой памяти присутствует только один э^емж^ Р*-
Лелнемой блок-секции, что дает возмож
Ресурсы,
Адрес Исходное положение
ОООО PSECT PROGA
• • • •
• 0040 LISTA •> • • •
• и • •
• • PSECT I
0054 ENDA • • i (PROGA)
• • •
» ЕЕГ4 ’ WORD ENDA-LISTA+LISTC
• • • • • 1
• оооо • • PSECT PROGB >
• • I PSECT 2
♦ • / (PROGB)
• оооо • PSECT PROGC =
* • • 1 PSECT 3
0030 LISTC • • • ) (PROGC)
► •
»•
9 *
9 END
а
Команда
Операнд
Объектный код и
команды переме-
щения/связывания
для предложения
REF4 в PROQA
Поместить значение в стек
Поместить в стек базу PSECT
плюс смещение
Сложение
Запомнить слово
Значение-14
PSECT=3{PR0GC},
смещение ^30
6
Рис. 3.19. Пример использования механизма перемещения и связы? |!1Я
ЭВМ VAX.
Третий тип — это системные блок-секции (system i'!--
I акая блок-секция предназначена для работы на машн>'11'
поддержки операционной системы. (Операционная систем 1 '
сама является системной блок-секцией.) Эти блок-секинн «
171
пользуются только для специальных целей. По сравнению с
другими типами блок-секций системная блок-секция имеет бо
лее простую структуру.
Программа связывания VAX выполняет обычные функции
по перемещению и связыванию программ. В дополнение к это
му она делает часть работы, которая в других системах выпол-
няется ассемблером или компилятором. Например, ассемблер
VAX не собирает все части программных секций в единую
объектную программу. Эта реорганизация осуществляется про-
граммой связывания. Аналогично ссылки между различными
программными секциями, ассемблируемыми совместно, обраба-
тываются программой связывания под управлением последова-
тельности команд сгенерированной ассемблером, и в отличие
от многих других систем в системе VAX не требуется явного
объявления внешних имен. (Это один из примеров того, на-
сколько мощным является используемый в системе VAX способ
командного управления связыванием.)
Ссылки между раздельно ассемблируемыми программными
секциями обрабатываются так, как было описано в разд. 3.2.
Используемые имена дожны быть объявлены глобальными (т. е.
внешними). Определения глобальных имен являются составной
частью объектного представления и используются программой
связывания для разрешения внешних ссылок между програм-
мными секциями. Различают два типа внешних ссылок — силь-
ные (strong) и слабые (weak). Сильные ссылки обрабатываются
обычным образом. Разрешение слабых ссылок осуществляется
только в том случае, если секция, в которой определены соот-
ветствующие имена, присутствует во входном потоке програм-
мы связывания. Автоматический библиотечный поиск для этих
ссылок не делается. Неразрешенные слабые ссылки не рассмат-
риваются как ошибки. Вместо этого им присваивается нулевое
значение. Одно из применений таких слабых ссылок — тестиро-
вание модульных программ. В этом случае может возникнуть
желание протестировать часть программы прежде, чем будут
написаны все подпрограммы. Если все вызовы к отсутствую-
щим подпрограммам идентифицировать как слабые ссылки, то
программу можно будет беспрепятственно загрузить и испол-
нять. Конечно, если программа попытается вызвать отсутствую
Шую подпрограмму, то в результате будет 3afi’IIbC'IP.0B^Y<.
ошибка. (Редактор связей System/370 и загрузчик ~ j-
BER допускают использование похожих слабых ссылок.) п
Определения глобальных переменных обычно отс^ • на.
исполняемой блок-секции, поскольку эта секция не Р - ‘
йена для повторной обработки с помощью прог’ • редСтв от-
дания. Однако в случае использования неко) . [- бд0К.сеКции
ладкй глобальные имена остаются в испси 00бщеНий. В раз-
и применяются при выводе диагностичес v ~~
делаемой блок-секции определения некоторых глобальных имен
сохраняются для того, чтобы обеспечить возможность связыва-
ния этой секции с другими программами. Эти имена, называе-
мые общими (universal) именами, задаются с помощью команд
программы связывания. Глобальные имена, не объявленные об-
щими, в разделяемой блок-секции не сохраняются.
Программа связывания ЭВМ VAX не поддерживает овер-
лейные программы. Частично это вызвано тем, что в системе
VAX предоставляется виртуальная память большого объема
Разработчики системы сочли, что большой объем виртуальной
памяти и применение алгоритмов управления этой памятью де-
лают ненужным использование оверлейных структур. (Напом-
ним, однако, что в System/370 редактор связей поддерживает
оверлейные программы и на системах с виртуальной
памятью.)
Дополнительную информацию по системе VAX вы можете
найти в DEC [1982] и DEC [1978].
3.5.3. Загрузчик ЭВМ CYBER
Формат объектной программы, используемый в системе
CYBER, отчасти более сложный, чем формат УУМ/ДС. Однако
он содержит ту же самую базовую информацию. Для зада-
ния информации о связывании используется механизм, сход-
ный с рассмотренными нами записями-модификаторами. Родст-
венный механизм может быть использован для описания требу-
емых перемещений. Наряду с этим для описания перемещении
может использоваться аппарат, похожий на аппарат масок пе-
ремещения, рассмотренный нами в разд. 3.2.1. Маски переме-
щения особенно полезны в системе CYBER, поскольку в ней
нет относительной адресации. Это означает, что в общем слу-
чае программы CYBER содержат намного больше величии,
требующих перемещения, чем аналогичные программы для
VAX или System/370.
В каждом слове CYBER может храниться не одна команда,
а несколько. Поэтому в маске перемещения недостаточно иметь
по одному разряду на каждое слово. Поскольку в СМИ
адреса оперативной памяти могут присутствовать только
командах, использующих 30-разрядный формат, то имеется пять
возможных вариантов размещения перемещаемой величины
внутри слова:
1. перемещение не требуется;
2. перемещаемое значение находится в левой полоню •
слова;
3. перемещаемое значение находится в правой половищ
слова;
слооа;"С₽еМСЩаеМЫе ЗВа"СИН” "аходя™ ° обеих половинах
„ого'с"ов1МеЩаеМОС зна,енпе "водится в середине 30-разряд.
Поэтому, когда используется аппарат масок перемещения
каждому слову сопоставляется 4-разрядное поле. э!о поле е’
пользуется для кодирования перечисленных выше вариантов й
для указания операции, которую надо выполнить для модифи-
кации перемещаемых значений (либо прибавить базовый адрес
к перемещаемому значению, либо вычесть).
Загрузчик CYBER поддерживает оверлейные программы но
на их структуру накладываются более жесткие ограничения.
Оверлейная структура ограничена максимум тремя уровнями.
Сегмент идентифицируется упорядоченной парой целых чисел и
может содержать только одну входную точку. Каждый сегмент,
кроме корневого, загружается по явному запросу. Автоматиче-
ская загрузка сегментов не предусмотрена. Прикладные про-
граммы могут запросить загрузку сегмента, обратившись к опе-
рационной системе. В качестве альтернативы допускается
использование небольшого резидентного загрузчика, обеспечи-
вающего оверлейную загрузку. Этот загрузчик может быть
включен в корневой сегмент.
Имеется также и более мощное средство организации овер-
лейного процесса, которое называется сегментацией (segmenta-
tion). Сегментированная программа также должна иметь дре-
вовидную структуру, однако допускается использование более
трех уровней и каждый сегмент может иметь несколько вход-
ных точек. Разрешается, кроме того использовать оверлейные
программы, размещенные в нескольких областях памяти. Такая
организация оверлейной структуры похожа на то, что мы рас-
сматривали для System/370 (хотя и используется другая тер-
минология). Программист с помощью командного языка може>
явно задать древовидную структуру,, указав, какие программы
должны включаться в соответствующие сегменты. Если до 111
сделано, то загрузчик распределяет программы между CUMtH
тами, исходя из анализа существующих между ними висшп .
В дополнение к стандартным функциям затР>^111}4
позволяет создавать так называемые капсулы ( ппогоамм,
су.,а состоит из одной или нескольких
связанных между собой и записанных в того чтобы
позволяющем осуществлять быструю загРУ у • ' ’ 1С програм-
загрузить капсулу в оперативную память, Р ‘ 'ик (Fast Dy*
мы могут вызвать быстрый динамимое у FDL более эф-
namic Loader — FDL). Загрузка с "J ’ требует меньших
фективна, чем другие методы за ру * ,
ресурсов оперативной памяти, однако она накладывает более
жесткие ограничения и сложнее в использовании.
Дополнительную информацию о загрузчике CYBER можно
найти в CDC [19826].
Упражнения
Раздел 3.1
1. Определите двоичный формат объектной программы для УУМ и на-
пишите абсолютный загрузчик (на языке ассемблера УУМ), позволяющий
загружать программы в этом формате.
2. Опишите метод преобразования объектной программы, формат кото-
ром использует символьное представление ассемблированного кода (см
рис. 3.1а) в машинное представление. Как бы вы реализовали его на языке
ассемблера УУМ?
3. В чем заключаются преимущества и недостатки реализации загруз-
чика на языке высокого уровня, например таком, как Паскаль? Какие
проблемы возникают в этом случае и как их можно преодолеть?
Раздел 3.2
1. Модифицируйте алгоритм на рис. 3.10 таким образом, чтобы он вы-
полнял настройку относительных адресов при помощи масок перемещения.
Связывание по-прежнему выполняется с помощью записей-модификаторов.
2. Предположим, что в некоторой ЭВМ в основном используется прямая
адресация, но имеются различные командные форматы. Какие проблемы
возникают в связи с этим, если для настройки относительных адресов ис-
пользовать маски перемещения? Как их можно разрешить?
3. Примените алгоритм, показанный на рис. 3.10, для связывания и за
грузки объектной программы на рис. 3.8. Сравните ваш результат с тем,
что изображено на рис. 3.9.
4. Предположим, что PROGA, PROGB и PROGC те же, что и ।
рис. 3.9. Покажите, как изменится объектная программа (включая записи
тела программы и записи-модификаторы), если в каждую программу до
бавить следующие предложения:
REF9 WORD
REF10 WORD
REF11 WORD
REF12 WORD
REF13 WORD
LISTC
LISTB —3
LISTA + LISTB
ENDC — LISTC — 100
LISTA - LISTB - ENDA + ENDB
5. Примените алгоритм,
загрузки модифицированной
показанный на рис. 3.10, для связывания >
объектной программы, сгенерированной -
в упр. 4.
6. Включите в алгоритм
на рис. 3.10 средства для обнаружения
ражениях некорректного использования внешних имен. (Список !• ,
см. в разд. 2.3.5.) Какие проблемы возникают при проведении по >
проверок?
7. Модифицируйте алгоритм на рис. 3.10 так, чтобы в нем hcih’-11'-1
лись номера ссылок, как это было описано в разд. 3.2.3.
8. В некоторых загрузчиках используется косвенная схема
Дли того чтобы использовать подобную схему в УУМ/ДС, аесемМч'
175
жен был бы сгенерировать cnncr.v
п предположениях EXTREF (ОлиУп ЭТеЛей для всех имен „
С помощью за,,исен-модн<Ьик'ат<.п^ Указатель на каждЛ?* ntpe4,lc-ieinibiX
значения адресов соо?вё?ствгюших загРуэ.и,ку было кба^ внешнее имя »
„пешиие ссылки можно было бы осу"
С.ИВК через эти указатели. Так. ..пр’К^Т.нЯ^'»» «““« а.™
L DA X Y 2.
(где XYZ — внешняя ссылка)
имела вид
ассемблировалась бы так.
как «ли бы 011а
LDA 3PXYZ
где PXYZ — указатель на XYZ. В чем преимущества и недостатки этого
метода?
9. Предложите проект однопрослютрового связывающего загрузчика Кч-
кие ограничения (если они нужны) требуется наложить в этом случае1
В чем преимущества и недостатки такого однопросмотрового загрузчика?
10. Некоторые языки программирования разрешают размещать данные
общих областях памяти ”. Исходная программа может содержать не-
сколько общих областей (с разными именами). Мы можем рассматривать
кяждую общую область как отдельную управляющую секцию.
ка*прц связывании и загрузке программ общим областям с одинаковыми
менами присваивается один и тот же начальный адрес. (Эти общие об-
*М ти в разных программах могут иметь различную длину.) Таким образом.
ЛЭ Гиянпивается соответствие между переменными общих областей, объяв-
У .,Гми в различных программах. Любые данные, записанные в общую
деи,|Ь1П • программой, становятся доступными для других.
°бЛТЛ мог бы загрузчик обрабатывать такие общие области? (Презло-
жятеКепосо°6 модификашш алго%™ » Р«с. 3.10 для о«™.
Раздел 3.3
’ 1. Модифицируйте алгоритм на рис. 3.10 так, чтобы он для разрешения
МНВШИИХ ссылок обеспечивал автоматический библиотечный поиск. Вы мо!
Жете считать, что доступ к библиотекам осуществляется с помощью ccpi
висных процедур операционной системы.
2. Модифицируйте алгоритм иа рис. 3.10 так, чтобы он позволял обра-
батывать команды CHANGE, DELETE и INCLUDE, описанные в разд. 3.3.2.
Если потребуется, вы можете ввести необходимые ограничения на их ис-
пользование.
3. Предположим, что загрузчик готовит листинг, который включает по.
только адреса, присвоенные внешним именам, но и таблицу перекрестии •.
ссылок между загружаемыми управляющими секциями. Какая информапь i
может быть полезна в таком листинге? Коротко опишите способ
-'той возможности и дайте определения необходимых для это j
Данных.
4. Рассмотрим оверлейную структуру, Только' из В,Р во
положим, что подпрограмма Н может быть „погоамме? (Считаем, что
" из С. Как это можно реализовать в °^3рл" ме11ЯютСж)
«Равила оверлея, определенные в разд. 3. . , яппрсов сегментам мер.
5. Опишите алгоритм назначения памяти, необходимый для
Шейной структуры, принимая во вин. •
Иещеиия SEGTAB и OVLMGR. .
----------- „„ COMMON язык. Фортран.-Прии. Р>
L Имеются в виду области ти
6. Во время выполнения оверлейной программы существует много раз-
личных наборов сегментов, которые могут находиться в памяти в различ-
ные моменты времени. Па рис. 3.146 показаны три возможных варианта
для программы на рис. 3.12а. Приведите другие варианты, используя ана-
логичную форму представления.
мы
7. Дайте краткое описание процедуры управления оверлеем, которую
назвали OVLMGR. Определите необходимые для нее структуры данных.
- — r-w’ • г • К I
8. Предположим, что мы хотим разрешить иметь в сс
ной программы более чем одну входную точку. Например
рис. 3.12а мы хотели бы непосредственно из сегмента Л
к входу D, либо к входу Е. При этом независимо от того, по какому входу
будет сделан вызов, должен загружаться весь сегмент D/Е. Каким образом
может быть реализована такая возможность — загрузчиком и (или) ме-
неджером оверлея?
в сегментах оверлеи-
». в программе па
сегмента Л обращаться либо
9. В описанном нами оверлейном пппиаггг ~
к другому сегменту вызывают оверлейную загруз^0 КпРСЛа"" Убавления
реализовать оверлейный процесс так, чтобы ссылка ня »яи...М°Ж,’° было г,ь*
лила к оверлейной загрузке? Вы можете ввести любые i.paL™** ’'Р"01’-
вашему мнению, ограничения, 1 любые, необходимые по
Раздел 3.4
1, Определите формат модуля, подходящий для представления связан-
пой программы, генерируемой редактором связей. Будем считать, что свя-
занная программа не предназначена для повторной обработки с помощью
редактора связей. Опишите алгоритм перемещающего загрузчика, который
можно использовать для загрузки модулей данною форма i а.
2. Рассмотрим следующие варианты храпения, связывания и исполне-
ния пользовательской программы.
а) Хранится только исходная программа; при каждом запуске про-
граммы она переассемблируется и загружается связывающим загрузчиком.
б) Хранятся исходная программа и ее объектное представление; и;ш
каждом запуске программы она загружается с помощью связывающею за-
грузчика.
в) Хранятся исходная программа и вариант программы, подготовлена
редактором связей, в котором оставлены неразрешенными ссылки на он
лиотечные подпрограммы; при каждом запуске программы она ззгруж।
с помощью связывающего загрузчика.
исходная программа и вариант программы, подготов
котором разрешены все внешние ссылки пр:!
------------------------------------------- ~ rtmHiArjQ. ''II -
г) Хранятся
ный редактором
каждом запуске
грузчика.
д) Хранятся
ный редактором
связен, в 1____г_... ___
программы она загружается с помощью связывающею
исходная
связей, в
программа и вариант программы, подготов
_____ котором разрешены все внешние ссылки и в за-
полнена настройка относительных адресов; при каждом запуске програм
она загружается с помощью абсолютного загрузчика.
Укажите условия, при которых целесообразно использовать каждые
этих вариантов. Предполагается, что в исходной программе не дел
никаких изменений.
3. Динамическое связывание и оверлейная загрузка имеют много
черт. Сопоставьте эти два подхода с точки зрения эффективности, пр1'
использования и других важных, на ваш взгляд, факторов. В каких ел)
каждый из этих подходов предпочтительнее другого?
4. Динамическое связывание, как оно было описано в разд. 3 I •••
Дотает только для передачи управления, Как его можно приспособив»
того, чтобы оно Обеспечивало динамическую загрузку и ппи
данные? 3 н при ссылках на
К. Предположим, что подпрограмма, загруженная с помощью динами
ческой загрузки, должна оставаться в оперативной памяти до окончания
главной программы. Предложите средства повышения эффективности ди-
намического связывания за счет того, что операционная система будет ис-
пользоваться только для загрузки программы, но не для передачи на неё
управления.
6. Предположим, что требуется удалить из памяти динамически загру-
женную подпрограмму (для повторного использования пространства памя-
ти). Будет ли предложенный вами в упр. 5 метод работать в этом случае?
Какие возникают здесь проблемы и как они могут быть разрешены?
7. Предположим, что нажатие па пульте УУМ/ДС кнопки «старт си-
стемы» вызывает чтение с вводного устройства 128-разрядной записи, ко-
торая разметается в оперативной памяти, начиная с адреса 0000. После
того как запись прочитана, управление автоматически передается по адре-
су 0000. Какие команды должны находиться в первой раскручивающей
записи для того, чтобы можно было загрузить следующую за ней абсолют-
ную объектную программу? Для раскручивающей записи н объектной про-
граммы вы можете выбрать любой удобный вам формат.
Глава 4. Макропроцессоры
В этой главе мы рассмотрим функции и способы реализации
макропроцессоров. Макроинструкции представляют собой удоб-
ное средство записи часто используемых групп предложений
исходного языка программирования. Процесс замены макроин-
струкций соответствующими группами предложений, осущест-
вляемый макропроцессором, называется макрорасширением,
расширением макроинструкций или макрогенерацией. Таким об-
разом, макроинструкции позволяют программисту записать
компактный вариант своей программы, оставляя все техниче-
ские детали, связанные с получением окончательного текста,
макропроцессору.
Основной функцией макропроцессора является замена одних
групп символов или строк на другие. За исключением некото-
рых специальных случаев, макропроцессор не анализирует
смысл обрабатываемого им текста. На устройство и возмож-
ности макропроцессора может повлиять форма предложений
используемого языка программирования; смысл этих предложе-
ний и вопросы трансляции их в машинные коды не имеют не-
посредственного отношения к процессу макрогеиерации. Поэто-
му механизм работы макропроцессора практически не связан
со структурой машины, на которой он должен работать.
Наиболее часто макропроцессоры применяются при про-
граммировании на языке ассемблера. Мы также будем исполь-
зовать язык ассемблера машины УУМ для иллюстрации боль-
шинства обсуждаемых концепций. Надо, однако, иметь ввиду,
что макропроцессоры могут быть также полезны при програм-
мировании на языках высокого уровня, на командных языках
операционной системы и т. д. Кроме того, имеются макропро-
цессоры общего назначения, которые не связаны непосредствен-
но с каким-либо конкретным языком. В последующих разделах
этой главы мы кратко обсудим эти более общие случаи исполь-
зования макросредств.
В разд. 4.1 вводятся основные понятия, включая «макро-
определение» и «макрорасширение». В нем также содержится
описание алгоритма работы простого макропроцессора.
В разд. 4.2 обсуждаются более сложные возможности, которы-
ми обладают многие макропроцессоры: порождение уникальных
меток, условная макрогенерация и использование ключевых па-
раметров в макроопределениях. Все эти возможности являются
машинно-независимыми. Поскольку устройство
ров не связано непосредственно со структурой ГР°ЦССС0'
не содержит раздела, посвященного машинно ТавиЛ, ГЛава
бенностям макропроцессоров. ° зависнмьш осо-
В разд. 4.3 описаны некоторые дополнительные вочмо'кигл
макропроцессоров. Одна из них (рекурсивная макр“е"ерХя1
оказывается связанной с внутренней структурой макроТоц”
сора; другие относятся к связям макропроцессора с так?1м,;
компонентами системного обеспечения, как ассемблер или ком
пилятор. 1 *
Заключительный разд. 4.4 содержит краткое описание трех
реальных макропроцессоров. Один из них является макоопоо-
цессором общего назначения, а два других предназначены тля
использования при программировании на языке ассемблера
В главе приводятся ссылки на литературу, содержащую трутне
примеры макропроцессоров.
4.1. Основные функции макропроцессоров
В этом разделе мы рассмотрим общие для всех макропро-
цессоров функции. В разд. 4.1.1 обсуждаются макроопределе-
ния, процессы макровызова и макрогенерации с учетом пара-
метров. В иллюстрирующих примерах используется язык
ассемблера УУМ/ДС. В разд. 4.1.2 описываются однопросмот-
ровый алгоритм работы простого макропроцессора и необходи-
мые для его работы структуры данных. В последующих разделах
этой главы обсуждаются вопросы реализации некоторых допол-
нительных возможностей.
4.1.1. Макроопределения и макрорасширения
На рис. 4.1 изображен пример программы для УУМ/ДС, в
которой используются макроинструкцпи. Эта программа выпол-
няет те же функции и имеет ту же логику, что и фрагмент,
программы, изображенной на рис. 2.5. Изменен только способ
нумерации предложений.
В этой программе определены и используются две n • '
струкции RDBUFF и WRBUFF. Функции и логику ма^
определения RDBUFF те же, что и у ПОД11р7 \uRBUFF ана-
изображенной на рис. 2.5; макроопределение WRBUH^
логично подпрограмме WRREG. Эти макроо р предложения
ся в исходной программе непосредственно после пр д
В них используются две повые д11реДдскоаС(строка Ю)
MACRO и MEND. Первое предд0^^1Я. Текст в поле метки
идентифицирует начало макроопр l
5 COPY START 0 КОПИРОВАНИЕ ФАЙЛА
10 15 RDJBUFF MACRO INDEV , &BUF ADR, &RECLTH
20 . МАКРОС ДЛЯ ЧТЕНИЯ В БУФЕР
25
30 35 CLEAR CLEAR X A ОЧИСТКА СЧЕТЧИКА ЦИКЛА
40 CLEAR S
45 кгл +LDT ♦ 4096 УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
TH »X'6INDEV* ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
JEQ 3 ЦИКЛ ОЖИДАНИЯ готовности
60 Ru =X'MNDEV' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
65 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
70 75 JEQ STCH *+11 6BUFADR,X ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ ЗАПИСЬ СИМВОЛА В БУФЕР
80 T1XR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
85 JLT *-19 ДЛИНЫ ЗАПИСИ
90 SIX &RECLTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
95 MEND
00 WRBUFF MACRO MJUTDEV. &BUFADR, 4.RECLTH
105
110 . МАКРОС ДЛЯ ЗАПИСИ ИЗ БУФЕРА
115 N
120 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
125 LDT &RECLTH
130 LDCH 6BUFADR,X ВЫБОРКА СИМВОЛА ИЗ БУФЕРА
135 TD =X'60UTDEV' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
140 JEQ *-3 ЦИКЛ ОЖИДАНИЯ готовности
145 WD =X40UTDEV' ЗАПИСЬ СИМВОЛА
150 TIXR T ЦИКЛ ПОКА ВСЕ СИМВОЛЫ НЕ БУДУТ
155 JLT *-14 ЗАПИСАН?!
160 MEND
165 «
170 . ОСНОВНАЯ ПРОГРАММА
175 СОХРАНЕНИЕ АДРЕСА ВОЗВРАТА
180 FIRST STL RETADR
190 CLOOP RDBUFF Fl,BUFFER, LENGTH ЧТЕНИЕ ЗАПИСИ В БУФЕР
195 LDA LENGTH ПРОВЕРКА НА КОНЕЦ ФАЙЛА
200 COMP #0 ВЫХОД ПО КОНЦУ ФАЙЛА
205 JEQ ENDFIL
210 WRBUFF 05,BUFFER,LENGTH ЗАПИСЬ ВЫХОДНОЙ ЗАПИСИ
215 J CLOOP ЦИКЛ
220 ENDFIL WRBUFF 05,EOF,THREE ЗАНЕСЕНИЕ МАРКЕРА КОНЦА ФАЙЛА
225 J QRETADR
230 EOF BYTE C'EOF'
235 THREE WORD 3
240 RETADR RESW 1
245 LENGTH RESW 1 ДЛИНА ЗАПИСИ
250 BUFFER RESB 409<5 БУФЕР ДЛИНОЙ 4096 БАЙТ
255 END FIRST
с. 4.1. Использование макросов в программе для УУМ/ДС.
В поле операнда именем этого макроопределения,
распределения R \п.ЛЯТСЯ имена формальных параметров .мак-
иа ра£еХ МаКроязь,ке имена всех" формальных
зволяетсущеас^вля7ьСчамр^ЦСн?1В0Л0М & (^персанд), что по-
апческие в пплио™ замену формальных параметров на флк-
“ в процессе макрогенерации. Имя и параметры макро-
са определяют шаблон или прототип используемой поогоам
мистом макроинструкции. После директивы MACRO следуют
предложения, составляющие тело макроопределения (строки с
1о по 90). Именно эти предложения и будут порождены в про-
цессе макрогенерации. Директива ассемблера MEND (стро-
ка 95) является признаком конца макроопределения Опретеле
пне макроса WRBUFF (строки с 100 по 1G0) имеет аналогич-
ную структуру.
Основная программа начинается со строки 180. Предложение
в строке 190 является предложением макроинициализации
Оно определяет имя макроинструкции, которая должна быть
инициализирована, и аргументы (фактические параметры), ко-
торые должны быть использованы в процессе макрогенерации
при порождении макрорасширения. (Предложение макрокници-
ализации часто называют также предложением макровызова
или просто макровызовом. Для того чтобы избежать путаницы
с предложениями вызова процедур и подпрограмм, мы пред-
почитаем использовать термин «макроинициализация» *>. Как
мы увидим, процесс макроинициализацип совершенно отличен
от процесса вызова подпрограммы.)
Читатель должен сравнить логику головной программы на
рис. 4.1 с логикой программы на рис. 2.5, помня о схожести
функций RDBUFF и RDREG, WRBUFF и WRREG.
Программа на рис. 4.1 может быть подана на вход макро-
процессора. На рис. 4.2 изображена результирующая програм-
ма. Определения макроинструкций в ней отсутствуют, поскольку
после порождения макрорасширений они уже не нужны.
Каждое предложение макроинициализацип превратилось г.
предложения видоизмененного тела макроопределения, в кото-
ром формальные параметры, описанные в макропрототипе (за-
головке макроопределения), заменены аргументами предложе-
ния макроинициализацип. Между аргументами и параметрами
имеется позиционное соответствие: первый аргумент в предло-
жении макроинициализацип соответствует первому параметру в
макропрототипе и т. д. Например, при расширении предложе-
ния макроинициализации в строке 190 параметр &INDEV всюду,
где он встречается в теле макроопределения, заменен на аргу-
мент F1. Аналогично &BUFADR заменен на BUF1-ER и
&RECLTH заменен на LENGTH.
Строки 190а—1901 представляют собой полное расширение
инструкции макроинициализации в строке 190. Строки коммен-
тариев внутри тела макроопределения удалены, однако коммен-
тарии внутри предложений языка остались. Обратите внима
° Этот введенный автором термин не является об111^"^',',/,ТЬ1обознач1ии-
литературе, так же, впрочем, как и термин «макропр •
Щий заголовок макроопределения. — Прим. ред.
5 COPY START 0
180 FIRST STL RETADR
190 .CLOOP RDBUFF Fl. BUFFI
190а CLOOP CLEAR X
190b CLEAR A
190с CLEAR S
190d +LDT ♦4096
190е TD «X'Fl*
190Г JEQ *-3
190g RD »X'F1'
190h COMPR ArS
190i JEQ *♦11
190 J STCH BUFFER,X
190k TIXR T
1901 JLT *-19
190м STX LENGTH
195 LDA LENGTH
200 COHP ♦0
205 JEQ ENDFIL
WRBUFF
КОПИРОВАНИЕ ФАЙЛА
ЗАПОМИНАНИЕ АДРЕСА ВОЗВРАТА
LENGTH ЧТЕНИЕ ЗАПИСИ В БУФЕР
ОЧИСТКА СЧЕТЧИКА ЦИКЛА
УСТАНОВКА МАКС. ДЛИНЫ ЗАПИСИ
ПРОВЕРКА ВХОДНОГО УСТРОЙСТВА
ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
ПРОВЕРКА ОКОНЧАНИЯ ЗАПИСИ
ВЫХОД ПО КОНЦУ ЗАПИСИ
ЗАПИСЬ СИМВОЛА В БУФЕР
ЦИКЛ ДО ДОСТИЖЕНИЯ
МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ1
СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
ПРОВЕРКА НА КОНЕЦ ФАЙЛА
ВЫХОД ПО КОНЦУ ФАЙЛА
05,BUFFER,LENGTH ЗАПИСЬ БУФЕРА
210
210а
210b
210с
210d
210е
210Г
210g
21 Oh
215
220
CLEAR
LDT
LDCH
TD
JEQ
WD
TIXR
X
LENGTH
BUFFERS
=Х,05"
*-3
*=Х'05'
ОЧИСТКА СЧЕТЧИКА ЦИКЛА
*-14
CLOOP
05,EOF,THREE
ЧТЕНИЕ СИМВОЛА ИЗ БУФЕРА
ПРОВЕРКА ВЫХОДНОГО УСТРОЙСТВА
ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
ЗАПИСЬ СИМВОЛА
ЦИКЛ, ПОКА ВСЕ СИМВОЛЫ НЕ
БУДУТ ЗАПИСАНЫ
ЦИКЛ
ЗАНЕСЕНИЕ МАРКЕРА КОНЦА ФАЙЛА
ENDFIL WRBUFF
220a ENDFIL CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
220b LDT THREE
220c 4.DCH EOF,X ЧТЕНИЕ СИМВОЛА ИЗ ВУФЕРА
220d TD =X'05Z ПРОВЕРКА ВЫХОДНОГО УСТРОЙСТВА
220e JEQ *-3 ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
220Г WD ~XZ05' ЗАПИСЬ СИМВОЛА
220g TIXR T ЦИКЛ, ПОКА ВСЕ СИМВОЛЫ НЕ
220h JLT *-14 БУДУТ ЗАПИСАНЫ
225 J GRETADR
230 EOF BYTE C'EOF'
235 THREE WORD’ 3
240 RETADR RESW 1
245 LENGTH RESW 1 ДЛИНА ЗАПИСИ
250 BUFFER RESB 4096 БУФЕР ДЛИНОЙ 4096 БАЙТ
255 END FIRST
Рис. 4.2.
Программа на рис. 4.1 с макрорасширениями.
Строки комментар^ОИОниЯЛиКрОИНИЦИализацни вставлены ка,<
НЫХ предложениях ияп„ лужа'г для напоминания об исход-,
*ения макроИнициализацИТ7с"о°6ра)ММИСТОМ‘ прсд-’Ю'
метки первого ппр.-г (CLOOP) оставлена в качестве
иия. Это позволяет пппгпИЯ сгснеРпРоваН11ого макрорасшире-
нии аналогично anvruL , амм,,сту использовать макроннструк-
рение предложений мл.-п 1сгРукциям языка ассемблера. Расшн-
осуществляется аналогХоИИчХ^"3?ЩШ в строках 210 и 220
лизациях макоося WDRiipd . Метьте- что в двух макроинпцна-
зульгате „о^ы " ₽С
После обработки макропроцессором расширенный <Ьайл
(рис. 4.2) может быть использован в качестве входного *айл«
ассемблера. Бывшие предложения макроинициализацип будут
рассматриваться как комментарии, а сгенерированные noeiio
женин макрорасширения будут обрабатываться ассемблером в
точности также, как если бы они были написаны непосредст-
венно программистом.
Сравнение расширенной программы на рис. 4.2 с програм-
мой на рис. 2.5 показывает наиболее существенные различия
между макроинициализацией и вызовом подпрограммы. В про-
грамме на рис. 4.2 предложения из тела макроса WRBUFF
сгенерированы дважды: строки 210а—210h и 220а—2201т. В про-
грамме на рис. 2.5 соответствующие предложения имеются
лишь в единственном экземпляре в подпрограмме WRREG
(строки 210—240). Это является общим правилом. Предложе-
ния, составляющие расширение макроса, генерируются (и со-
ответственно ассемблируются) каждый раз, когда соответствую-
щий макрос инициализируется. Предложения подпрограммы
имеются лишь в единственном экземпляре независимо от того,
сколько раз эта подпрограмма вызывается.
Заметьте также, что наши макроинструкции были написаны
таким образом, что тело макроопределения не содержало ме-
ток. На рис. 4.1 в строке 140 находится предложение
«JEQ *—3», в строке 155 — предложение «JLT-»—14». Со-
ответствующими предложениями в подпрограмме WRREC
(рис. 2.5) являются «JEQ WLOOP» и «JLT WLOOP», где
WLOOP — метка TD инструкции, проверяющей состояние уст-
ройства вывода. Если бы эта метка была в строке 135 тела
макроопределения, она была бы сгенерирована дважды: в стро-
ках 210b и 220d (рис. 4.2). Это привело бы к ошибке (дважды
определенная метка) во время работы ассемблера. Для того
чтобы избежать дублирования меток, мы исключили их из тел
наших макроопределений.
Использование предложений, подобных «JLT *—14», счи-
тается признаком плохого стиля программирования. Их при-
менение отчасти может быть оправданно внутри тела макро-
определения, однако и это можно считать плохим стилем уве-
личивающим вероятность появления ошибок. В разд. 4.2.2 мы
обсудим, как можно избежать подобных конструкций.
4.1.2. Макропроцессор. Таблицы и логика
Легко себе представить двухпросмотровый
в котором все макроопределения обрабатываюрп ВТ(>
просмотре, а все предложения макР0^,,,иц1,а‘'’"'’|1есс0|) не допу-
ром. Однако такой двухпросмотровыи макро ।
1 2 MACROS RDBUFF MACRO MACRO Л to to {стандартная версия для УУМ}
3 WRBUFF MEND <конец RDBUFF)
я MACRO • * &QUTDEV , 6BUFADR, W<ECLTH {стандартная версия для УУМ)
5 MEND to to (конец WRBUFF)
6 MEND (конец MACROS) а
1 MACROX MACRO (версия макросов для УУМ/ДС}
2 RDBUFF MACRO «* 4.1NDEV, &BUFADR, &RECLTH (версия для УУМ/ДС}
3 MEND (конец RDBUFF}
4 WRBUFF MACRO &OUTDEV, &BUF ADR, 4.RECLTH (версия для УУМ/ДС}
5 MEND to {конец WRBUFF)
6 V MEND (конец MACROX) б.
Рис. 4.3. Пример использования макроопределения внутри тела другого мак-
роопределения.
ДРУГИХ макпп^п 7Ле 0ДН0Г0 макРоопределения опредслснин
быть обработаны ппи°пК°ЛЬКУ ВСе макР°°пределеиия должны
макрорасширений)? РВОМ пРосмотРе до выполнения любых
други^^лСгрт Рг°Да опРеДеление одних макросов с помощью,1
ноимепя пп'1 м ЫТЬ |!ногда п°Дезно. Рассмотрим в качестве
роса Р/МАСрЛчСООПРеДеЛеНИЯ На рнс- 43- Тело первого мак'
RDBUFF WDRI ГСсодержит Предложения, определяющие
(оие А’а\ WRBUFF и другие макроинструкции для УУМ
nPnit? Ь 1еЛ° ДРУГОГО макроопределения (MACROX) с<>
(пис 4 - °пРеделения тех же макросов для УУМ/ДС
стамлЯптиА;?ХОллРаМма’ предназначенная для использования на;
лрпонС гУУМ’ может инициализировать MACROS для опрс
может1яш^обходимь1Х ей макросов. Программа для УУМ/ДС
макпоспп циализиРовать MACROX для определения тех ее
Р в расширенной ДС версии. Таким образом, одна Д
______________4 |- Основные функции макропроцессоров 185
та же программа сможет работать как на стандартной УУМ
так и на УУМ/ДС (используя все ее дополнительные возмож-
ности). Единственное, что для этого надо сделать,—- это иници-
ализировать один из макросов: либо MACROS, либо A4ACROX
Важно понять, что само описание макроопределений MACROS
или MACROX не определяет RDBUFF и других макросов. Они
становятся доступными для использования только после завер-
шения обработки предложений макроинициализацип макоосоп
MACROS или MACROX •>. р
Однопросмотровый макропроцессор, который может пере-
ключаться с обработки макроопределений на выполнение мак-
рорасширений и наоборот, способен обрабатывать макроопреде-
ления, подобные изображенным иа рис. 4.3. В этом разделе
мы рассмотрим алгоритм работы и структуры данных такого
макропроцессора. Поскольку макропроцессор предполагается
однопросмотровым, любые макроопределения должны появлять-
ся в исходной программе прежде соответствующих предложе-
ний макроинициализации. Это ограничение практически по
оборачивается какими-либо неудобствами для программиста,
поскольку появление предложения макроинициализации до со-
ответствующего макроопределения смутит любого знакомяще-
гося с такой программой.
В нашем макропроцессоре используются три основные струк-
туры данных. Сами макроопределения находятся в таблице
макроопределений (DEFTAB), которая содержит макропрото-
типы и предложения, составляющие тело макроопределений (с
некоторыми модификациями). Строки комментариев, содержа-
щиеся внутри макроопределений, отсутствуют в таблице
DEFTAB, поскольку они не нужны на этапе макрогенерации.
Для повышения эффективности процесса подстановки аргумен-
тов ссылки на формальные параметры макроопределении пре-
образованы в их порядковые номера. Имена макросов содер-
жатся в таблице NAMTAB, которая, по существу, является
таблицей указателей на DEFTAB. Для каждого макроопреде-
ления таблица NAMTAB содержит указатели на начало и ко-
нец макроопределения, содержащегося в DEFTAB.
Третья структура данных — это таблица аргументов (ARG-
TAB), заполняемая на этапе обработки предложений макро-
инициализации. Как только такое предложение распознано, его
аргументы записываются в таблицу ARGTAB в соответствии с
их номерами в списке аргументов. В процессе макрогенерашш
аргументы из таблицы ARGTAB заменяют собой соответствию
щие формальные параметры в теле макроопределения.
По-видимому автор
грамму можно выполнять
определения. — Прим. ред.
Й"» ГууЙ/Дй «S
NAMTAB
DEFTAB
1 RDBUFF
RDBUFF &INDEY
CLEAR X
CLEAR A
CLEAR S
4 LDT #4096
TD С--Х’?Г
JEQ *~3
RD ~X’?U
COMPR A,S
JEQ *+11
STCH ?2,X
TIXR T
JLT *-19
STX ?3
MEND
.&ВиГАОНЛйЕСИН
ARGTAB
1
F1
BUFFER
3
LENGTH
6
Рис. 4.4. Содержимое таблиц макропроцессора для программы на рис. 4.1:
а — фрагменты таблиц NAMTAB и DEFTAB, связанные с макроопределе-
нием RDBUFF, б — содержимое таблицы ARGTAB для макроинициализации
RDBUFF в строке 190.
На рис. 4.4 показаны фрагменты содержимого этих таблиц
на этапе обработки программы, изображенной на рис. 4.1.
Рис. 4.4а содержит макроопределение RDBUFF, записанное в
таблицу DEFTAB, на начало и конец которого смотрят соот-
ветствующие указатели из таблицы NAMTAB. Обратите
внимание на позиционную нотацию, использованную для обо-
значения параметров: параметр &INDF превращен в ?1 (Ука‘
зывая на то, что это первый параметр в прототипе), парамо’Р
&BUFADR преобразован в ?2 и т. д. На рис. 4.46 изображе-
на таблица ARGTAB в том виде, в котором она окажется
время расширения макроса RDBUFF в строке 190. Для
макроинициализации первым аргументом будет F1, вторы"
BUFFER и т. д. Такая запись параметров делает проносе 4
замены на соответствующие аргументы существенно более
Фиктивным. Как только встречается конструкция ?п в сгро"
таблицы DEFTAB, за счет простых индексных операций
выбрать соответствующий аргумент из таблицы ARGTAR
Собственно алгоритм работы макропроцессора представпги
на рис. 4.5. Процедура DEFINE, которая вызывается как топь
ко распознано начало макроопределения, формирует соответ"
ствующие строки таблиц DEFTAB и NAMTAB Процедуоз
EXPAND записывает аргументы в таблицу ARGTAB и осуще<
ствляет расширение предложений макроинициализацип. Про-
цедура GETLINE, которая вызывается в нескольких местах ал-
горитма, выбирает очередную строку для обработки. Это может
быть строка из таблицы DEFTAB (очередная строка тела мак-
роопределения) или очередная строка входного файла в зави-
симости от того, какое значение имеет булевская переменная
EXPANDING.
Одна из особенностей этого алгоритма заслуживает даль-
нейших пояснений. Это обработка макроопределений внутри
тела других макроопределений (как на рис. 4.3). После того
как заголовок макроопределения записан в таблицу DEFTAB,
было бы естественно продолжать заполнять эту таблицу до тех
пор, пока не встретилась директива MEND. Этого, однако,
нельзя делать для примера, изображенного на рис. 4.3, по-
скольку директива MEND в строке 3 (конец макроопределения
RDBUFF) была бы интерпретирована как конец макроопреде-
ления MACROS. Для того чтобы обойти эту трудность, наша
процедура DEFINE содержит счетчик LEVEL. Каждый раз,
когда встречается MACRO, величина счетчика LEVEL увеличи-
вается на 1; по каждой директиве MEND его величина умень-
шается на 1. Нулевое значение этого счетчика означает, что
встретилась директива MEND, соответствующая исходной ди-
рективе MACRO. Этот процесс во многом аналогичен анализу
открывающихся и закрывающихся скобок при обработке ариф-
метических выражений. Для того чтобы убедиться, что вы по-
нимаете работу этого алгоритма, вы можете применить его
вручную к программе на рис. 4.1. Результат должен быть тот
же, что и на рис. 4.2.
Большинство макропроцессоров допускает использование
стандартных системных библиотек, содержащих наиболее часто
используемые макроопределения. В этом случае нет необхо-
димости иметь тела этих макроопределений в исходной про-
грамме— они выбираются из библиотеки тогда, когда это нуж-
но в процессе работы макропроцессора. В результате использо-
вание макропроцессора становится существенно более удобным.
Соответствующие макроопределения выбираются из оиблиотск!
тогда, когда это нужно в процессе работы макропроцесс j.<•
Одним из упражнений, приведенном в конце этой глав ’ ..ог0
ется дополнение алгоритма, изображенного на рис. »
рода возможностью.
begin (макропроцессор)
EXPANDING :=» FALSE
while OPCODE < > 'END' da
begin
GETLINE
PROCESSLINE
end Cwhile)
end (макропроцессор)
procedure PROCESSLINE
begin
поиск OPCODE в NAMTAB
if нашли then
EXPAND
else if OPCODE « 'MACRO' then
DEFINE
else записать исходную строку в Файл макрорасширения
end (PROCESSLINE} г прения
procedure DEFINE
begin
записать имя. макроопределения в NAMTAB
записать макропрототип в DEFTAB
LEVEL := 1
while LEVEL > 0 do
begin
GETLINE
if это не строка-комментарий then
begin
заменить вхождение имени К“ГО параметра на
занести строку в DEFTАВ
if OPCODE =* 'MACRO' then
LEVEL := LEVEL + 1
else if OPCODE = 'MEND' then
LEVEL := LEVEL - 1
end ( если не строка-комментарий}
end (while)
записать в NAHTAB указатели на начало и конец макроопределения
end (DEFINE)
procedure EXPAND
begin
EXPANDING := TRUE
взять первую строку макроопределения (заголовок) из DEFTAB
записать аргументы макроинициализации в ARGTAB
записать предложение макроинициализации как комментарий
while не конец макроопределения do
begin
GETLINE
PROCESSLINE
end (while}
EXPANDING := FALSE
end (EXPAND!
procedure GETLINE
begin
if EXPANDING then
begin
взять следующую строку макроопределения из DEFTАВ
заменить выражения ?к на аргументы из ARGIAB
end (if}
else
прочитать очередную строку входного Файла
end (GETLINE)
4.2. Машинно-независимые особенности
макропроцессора
В этом разделе мы обсудим некоторые расширения описан-
ных выше базовых функций макропроцессора. Как мы уже от-
мечали, эти расширения не связаны непосредственно с архитек-
турой машины, для которой создавался макропроцессор.
В разд. 4.2.1 описан метод конкатенации параметров макроин-
струкции с другими строками символов. В разд. 4.2.2 обсужда-
ется один из методов генерации уникальных меток, который
позволяет избежать частого использования относительной адре-
сации в теле макроопределения. В разд. 4.2.3 вводится и
иллюстрируется на нескольких примерах важное понятие ус-
ловного макрорасширения (условной макрогенерацин). Возмож-
ность изменения макрорасширения путем использования управ-
ляющих предложений делает макроинструкции существенно бо-
лее мощным и полезным для программиста средством.
В разд. 4.2.4 обсуждается определение и использование ключе-
вых параметров макроинструкцпй.
4.2.1. Конкатенация макропараметров
Большинство макропроцессоров допускает конкатенацию па-
раметров с другими строками символов. Предположим, напри-
мер, что программа содержит набор переменных с именами ХА I,
ХА2, ХАЗ, .... другой набор переменных с именами ХВ1, ХВ2,
ХВЗ, ... и т. д. Если над подобными наборами переменных
необходимо осуществить одинаковые действия, программист мо-
жет записать их в виде макроопределения. Его параметр дол-
жен так определить необходимый набор переменных (например,
А, В и т. д.), чтобы макропроцессор смог, используя значения
этого параметра, сконструировать в процессе макрогенерацин
все необходимые имена (ХА1, ХВ1 и т. д.).
Предположим, что такой параметр назван &ID. Тело макро-
определения может содержать предложение вила
LDA X&ID1
в котором параметр &1D должен быть сконкатенирован со
строкой, состоящей из символа X, расположенной до параметра,
и со строкой, состоящей из символа 1, расположенной после
параметра. Проблема состоит в том, что конец параметра ни-
как специально не обозначен (его начало легко может быть
идентифицировано по символу &). Таким образом, рассматри-
ваемое предложение может быть интерпретировано также как
Рис. 4.5. Алгоритм работы одноиросмотрового макропроцессор.!.
строка символов X, за которой следует параметр &1D1. В дав-
ние
ном конкретном случае макропроцессор сможет интерпретиро-
вать это предложение правильно. Однако если макроопределе-
параметров и &1D, и &ID1, то ситуация
5
2
з
содержит в качестве
SUM MACRO 4.1!
LM xejD-ot
ADD XAlD-^2
ADD ХШ-*3
STA X&IDdhS
MEND SUM 1 A
LDA XA1
ADD XA2
ADD XA3
STA XAS
SUM I BETA
4* LDA XBETA1
ADD XBETA2
ADD XBETA3
STA XBETAS
а
б
4.6. Конкатенация макро-
становится в принципе неразреши-
мой.
Большинство макропроцессоров
решает эту проблему введением
специального оператора конкатена-
ции. В макроязыке УУМ этот опе-
ратор записывается как —Преды-
дущее предложение на этом мак-
роязыке должно будет иметь вид
LDA X&1D -> 1
в
Рнс.
где конец параметра &1D четко
определен. Макропроцессор уничто-
жает все вхождения символа, обо-
значающего оператор конкатена-
ции, сразу же после завершения
подстановки параметров. Таким об-
разом, символ -> не появится в по-
рожденном тексте макрорасшире-
ния.
На рис. 4.6а изображено макро-
определение, в котором использу-
ется оператор конкатенации. На
рис. 4.66 и 4.6в изображены пред-
параметров. ложения макроинициализации и со-
ответствующие им тексты макрорас-
ширения. Для того чтобы убедиться в правильном понимании
работы оператора конкатенации, вы должны проследить весь
процесс порождения этих макрорасширений. Вы можете также
подумать о том, каким образом оператор конкатенации мог <'д
обрабатываться в алгоритме работы макропроцессора, подоб-
ном изображенному на рис. 4.5.
4.2.2. Генерация уникальных меток
Как мы уже говорили в разд. 4.1, тело макроопределсы
вообще говоря, не должно содержать обычных меток. Это при-
водит к необходимости использования в исходной програм
относительной адресации. Рассмотрим в качестве примера опре-
деление WRBUFF на рис. 4.1. Если бы команда TD в строку
135 была помечена, эта метка оказалась бы дважды опредс.н
ной (для каждой инициализации WRBUFF). Это, естественно,
не позволило бы ассемблеру получить готовую программу*
25 RDBUFF MACRO 6INDEV, IBUF ADR, &RECLTH
30 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
35 CLEAR A
40 CLEAR S
45 {‘.ПОР ♦LDT ♦4096 УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
50 TD =X'6INDEU' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
55 JEQ $LOOP ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
60 RD »X'MNDEV' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
65 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
70 JEQ $EXIT ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
75 STCH 6BUFADR.X ЗАПИСЬ СИМВОЛА В БУФЕР
80 TIXR T ЦИКЛ ДО ДОСТИ1ЕНИЯ МАКСИМАЛЬНОЙ
85 IEXIT JL T $LOOP ДЛИНЫ ЗАПИСИ
90 STX &RECLTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
95 MEMO
RDBUFF Fl,BUFFER ,LENGTH
30 CLEAR X ОЧИСТКА СЧЁТЧИКА ЦИКЛА
35 CLEAR A
40 CLEAR S
45 4LDT ♦4096 УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
50 $4AL00P TD . «X'Fl' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
55 JEQ $AALOOP ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
60 RD ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
65 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
70 JEQ $AAEXIT ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
75 STCH BUFFER,X ЗАПИСЬ СИМВОЛА В БУФЕР
80 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
85 JLT $AALOOP ДЛИНЫ ЗАПИСИ
90 $AAEXIT STX 6RECLTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
б
Рнс. 4.7, Генерация уникальных меток для макрогенерации.
Поскольку строку 135 в этом макроопределении нельзя по-
метить, в командах перехода на строки 140 и 155 появляются
относительные адреса *—3 и *—14. Использование относи-
тельной адресации в исходной программе еще может быть
приемлемым для коротких переходов типа JEQ *—3. Однако
для переходов к далеко расположенным командам подобная
запись является неудобной, увеличивает вероятность появления
ошибок, трудна для понимания. Многие макропроцессоры реша-
ют эту проблему за счет макрогенерации меток специального
вида.
Рис. 4.7 иллюстрирует один из способов порождения уни-
кальных меток. Макроопределение RDBUFF изображено на
рис. 4.7а. Метки, используемые внутри тела макроопределения,
начинаются специальным символом $. На рис. 4.76 изображены
предложения макроиницализации и соответствующие им текс-
ты макрорасширений. Все идентификаторы, начинающиеся сим-
волом модифицированы путем замены символа § на символы
$АА. При обработке других предложений макроннциализа-
цин символ $ будет заменен на §>ХХ, где XX — двухсимвольный
алфавитно-цифровой счетчик количества обработанных предло-
жений макроинициализации. При обработке первого встретив-
шегося в программе предложения макроинициализации XX
будет иметь значение АА. При обработке последующих пред-
ложений макроинициализации XX будет иметь значения АВ,
АС и т. д. (Если для счетчика XX используются только латин-
ские буквы и цифры, то подобный двухсимвольный счетчик по-
зволяет обработать в одной программе до 1296 предложений
макроинициализации.) Таким образом, в макрорасширениях,
соответствующих различным предложениям макроинициализа-
ции, метки будут различаться. Другие примеры будут изобра-
жены на рис. 4.8 и 4.10.
Язык ассемблера УУМ. допускает появление символа $ в
индентификаторах. Однако программисты предупреждаются о
том что этот символ не следует использовать в их программах.
Это’ позволяет избежать всяких конфликтов между идентифи-
каторами программиста и идентификаторами, порожденными
макропроцессором.
4.2.3. Условные макрорасширения
Во всех рассмотренных нами примерах использования мак-
роинструкций каждая инициализация некоторого макроса рас-
ширялась всегда в одну и ту же последовательность предложи
пни. Эти предложения могли различаться за счет подстановки
разных параметров. Однако их форма и последовательность
всегда были неизменными. Даже такие простые макросрсдств >
могут быть весьма полезны. Но большинство макропроцессор
может изменять также последовательность порожденных в про-
цессе макрогенерацин предложений (в зависимости от значении
аргументов в предложении макроинициализации). Подобная
возможность существенно увеличивает мощь и гибкость макро-
языка. В этом разделе мы рассмотрим типичный набор при-
ложений условной макрогенерацин. Другие примеры содержаi '
в разд. 4.4, посвященном описанию некоторых макропрон
соров.
В связи с обсуждаемыми в этом разделе возможное ж
часто используется термин «условное ассемблирование». 1 ' '
ствуют, однако, приложения макропроцессоров, никак не
за иные с программированием на языке ассемблера. Поэю-'.
мы предпочитаем термин «условная макрогенерацня».
Па рис. 4.8 приведен пример использования одного J.1; ,
ложений условной макрогенерацин, На рис, 4.8а изоор1
I 2. .Машнипо „езапненмые особенности макропроиоет,,.
макроопределение RDBUFF логика и функции
обсуждались. Это макроопределение содержит два РдопоУ>Ке
тельных параметра: &EOR, который определяет шестнаТиатё'
ричнын код, являющийся признаком конца запили
&MAXLTH, который определяет максимальную длину записи
которая может быть прочитана. (Как мы увидим любой из
этих параметров или оба сразу могут быть опущены при 111ш
циализации макроса RDBUFF.) н
Предложения в строках 44—48 этого макроопределения яв-
ляются примером простой условной структуры периода макро-
генерации. В предложении IF вычисляется булевское выраже-
ние, являющееся его операндом. Если значение этого выраже-
ния есть TRUE, то порождаются предложения, следующие за
предложением IF до тех пор, пока не встретится предложение
ELSE. В противном случае эти предложения опускаются и по-
рождаются предложения, следующие за ELSE. Предложение
ENDIF завершает условную конструкцию, начатую предложе-
нием IF. (Как обычно, альтернатива ELSE может быть опу-
щена.) Таким образом, если значением параметра &MAXLTU
является пустая строка (это означает, что соответствующий
аргумент был опущен в предложении макроинициализации), то
будет порождено предложение в строке 45. В противном случае
будет порождено предложение в строке 47.
Аналогичная конструкция содержится в строках 26—28.
Обратите внимание, что предложение, следующее за IF, не яв-
ляется строкой, которая должна быть порождена в процессе
макрогенерации. Это предложение является директивой макро-
процессора (SET), которая присваивает значение 1 переменной
&EORCK. Подобные переменные называются переменными пе-
риода макрогенерации. Они позволяют хранить нужные значе-
ния в период порождения текста макрорасширения. Любой
идентификатор, начинающийся символом & и не являющийся
параметром макроопределения, является переменной периода
макрогенерацни. Считается, что начальное значение всех таких
переменных равно нулю. Таким образом, если в нашем приме-
ре в предложении макроинициализацип будет задан аргу-
мент, соответствующий параметру &EOR, то значение парамет-
ра &EOR не является пустой строкой, и переменной &EORCK
будет присвоено значение 1. В противном случае она сохранит
свое исходное значение нуль. Значение этой переменной периода
макрогенерацни используется в условных структурах в строках
с 38 по 43 и с 63 по 73.
В предыдущем примере переменная периода макрогенерации
&EORCK использовалась для запоминания результата анализа
параметра &EOR (строка 26). В предложениях IF 'LTP0K"
и 63) можно было бы, конечно, вместо использования ПСР*‘_
ной &EORCK повторить исходное сравнение, в резулы а
7 Зак. 792
г л. 4. Макропроцессоры
25 26 RDBUFF MACRO IF tI?wMNEB^?DR,&RECLTH’l‘E°R’l'MAXl-TH
27 &EORCK SET 1
28 ENDIF
30 35 CLEAR CLEAR X A ОЧИСТКА СЧЕТЧИКА ЦИКЛА
38 IF (6E0RCK EQ 1)
40 42 LDCH RMO =X4E0R' A,S УСТАНОВКА СИМВОЛА EOR
43 ENDIF
44 IF (6MAXLTH £( 1 ">
45 46 +LDT else: ♦4096 МАКСИМАЛЬНАЯ ДЛИНА ЗАПИСИ = 4096
47 48 •FLDT ENDIF ♦&MAXLTH УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
50 55 • л $LOOP TD JEQ ^X'6INDEV' $LOOP ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
RD tX'&INUEV' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
IF <&EORCK EQ 1 ) * 1"
Z5 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
79 JEQ $EXIT ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
75 STCH ABUFADR,X ЗАПИСЬ СИМВОЛА В БУФЕР
ее TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
е5 JLT $LOOP ДЛИНЫ ЗАПИСИ
90 $ЕХ1Г STX &RECLTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
95 MEND
а
RDBUFF F3,BUF,RECL,04,2048
30 CLEAR X
35 CLEAR A
40 LDCH =X'04'
>42 RMO A,S
47 +LDT ♦2048
50 $AALOOP TD *X'F3'
55 JEQ $AALO0P
го RD =X'F3'
«5 COMPR A,S
70 JEQ SAAEXIT
75 STCH BUF.X
S3 TIXR T
65 JLT $AALOOP
90 $AAEXIT STX ARECL
ОЧИСТКА СЧЕТЧИКА ЦИКЛА
УСТАНОВКА СИМВОЛА E0R
УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНУ ЗАПИСИ
ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
ЦИКЛ О1ИДАНИЯ ГОТОВНОСТИ
ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
ЗАПИСЬ СИМВОЛА В БУФЕР
ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
ДЛИНЫ ЗАПИСИ
СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
которого это значение было получено. Однако исподы
переменной периода макрогенерации оправданно здесь х(> ,с,
уже потому, что оно указывает на то, что в обоих ПР ''
ниях IF используются одинаковые условия. Кроме гон
верка значения переменной может оказаться быстрее, 1
нторенис исходного сравнения, особенно если оно связан
числением сложных булевских выражений.
4.2. Машнино-незавиеиммо особенности мп.,.
RDBUFF BUFFER *
,LENGTH,,80
30 35 CLEAR CLEAR X A ОЧИСТКА СЧЕТЧИКА ЦИКЛА
47 50 55 60 75 80 85 90 +LDT $ABLOOP TD JEQ RD STCH TIXR JLT $ABEXIT STX ♦80 =X'0E' $ABLOOP’ *=X'0E' BUFFERrX T Sabloop LENGTH ПРОВ^К^ГОТОВНОСТ^^трп^' ЗАПИСИ цикл ожидания готовног™°ЙСТВА ЧТЕНИЕ СИМВОЛА в а ЗАПИСЬ СИМВОЛА В БУФеГ А цикл до Sr3Hirc^ СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
в
RDBUFF FlrBUFF, RLENG,04
30 35 CLEAR CLEAR X A ОЧИСТКА СЧЕТЧИКА ЦИКЛА
40 42 LDCH RMO e=X'04' A,S УСТАНОВКА СИМВОЛА EOR
47 50 +LDT tACLOOP TD ♦4096 =X'F1' УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
«JvJ JEQ $ACLOOP ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
60 RD =X'F1' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
65 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
70 •ЧГ* JEQ $ACEXIT ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
75 STCH BUFF,X ЗАПИСЬ СИМВОЛА В БУФЕР ’
80 TIXR T 1 ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
85 JLT SACLOOP ДЛИНЫ ЗАПИСИ
90 $ACEXIT STX RLENG СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
Рис. 4.8. Использование
условных предложений периода макрогенерацин
На рис. 4.86—г изображены макрорасширения, порожденные
тремя различными макроинициализациями, иллюстрирующие
работу предложений IF во фрагменте на рис. 4.8а. Вы должны
внимательно разобраться с этими примерами и убедиться, что
понимаете, каким образом было получено данное макрорасши-
рение, исходя из текста макроопределения и предложения мак-
роииициализации. „ ifavnn
Реализация только что описанных средств условной м р -
генерации достаточно проста. Макропроцессор должен
таблицу имен переменных периода макрогенерацин, со.I '
щую их значения. Эта таблица должна ПО„П°Л"^ГЬЛ^ г . Н11
дифицироваться при обработке предложении SE . МЯКпоге«
понадобилось текущее значение переменной периода м< Ч
нерации, оно берется из этой таблицы. предложение
Когда в процессе макрогенерации ветре 11Г1И<ение. Если
IF, вычисляется соответствующее булевсо: с _ абатывать стро-
ено истинно, то макропроцессор продолжа
ни из таблицы DEFTAB до тех поп пока на пгт
жение ELSE или ENDIF. Если встретилось предлХен^"els?'
то макропроцессор пропускает строки в таблице DFFTARSE’
предложения ENDIF. После предложения ENDIFM^nonn
нессор продолжает работать в обычном режиме р“акропро'
чение булевского выражения предложения' IF ложно то Z
ропроцессор пропускает строки в таблице DEFTAB ЗК"
пока не встретит ELSE ,,л„ ENDIF. Далее макройроце!Й
продолжает работать, как обычно. исссор
Предложенная выше реализация не допускает вложенных
конструкции IF. Вы можете подумать о том, как она должна
ynp.^S^”3' обрабатывать подобные структуры
Чрезвычайно важно попять, что проверка истинности булев-
ских выражений в предложениях IF осуществляется на этапе
макрогенерацни. К началу работы ассемблера все подобные
решения уже приняты. Образовалась только одна последова-
тельность предложений готовой программы (например, предло-
жения иа рис. 4.8в), а все директивы условной макрогенерацни
исключены. Таким образом, предложения IF периода макроге-
нерации дают программисту удобные средства записи различ-
ных вариантов своей программы. Эти средства существенно от-
личны от предложений, подобных COMPR (или предложений
IF в языках высокого уровня), которые осуществляют свои
проверки во время выполнения программы. То же относится и
к присваиванию значений переменным периода макрогенерацни
и другим директивам условной макрогенерации, которые мы
еще обсудим.
Условная конструкция периода макрогенерацни IF—ELSE—
ENDIF является механизмом, позволяющим однократно пере-
нести или пропустить некоторые строки из тела макроопределе-
ния в результирующую программу. На рис. 4.9а приведен при-
мер условных предложений периода макрогенерации другого
типа. На нем изображено модифицированное определение мак-
роса RDBUFF, назначение и функции которого те же, что и
раньше. Но с помощью этого макроса программист может
определить целый список признаков конца записи. Например, в
предложении макроинициализацип на рис. 4.96 параметру L ,
соответствует список (00, 03, 04). Любой из этих кодов явля
ется признаком конца записи. Для упрощения макроопределе
ния параметр &MAXLTH удален; максимальная длина записи
всегда полагается равной 4096.
В макроопределении на рис. 4.9а используется цикли1с у
конструкция WHILE периода макрогенерации. пРедл0*;н”
WHILE указывает на то, что последующие строки тела мак
определения до ближайшего предложения ENDW доджи •
гократно переноситься в результирующую программ}
25 RDBUFF MACRO &INDEV, &BUFADR, 6RECLTH, 6E0R
2/ 6EORCT SET ZNITEMSC6E0R)
30 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
35 CLEAR A
45 +LDT 44096 МАКСИМАЛЬНАЯ ДЛИНА ЗАПИСИ = 4096
50 SLOOP TD »X4INDEV' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
55 JEQ SLOOP ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
бе RD t=X'MNDEV' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
63 A.CTR SET 1
64 WHILE (6CTR LE &EORCT)
65 COMP ^X'00006EORL6CTRJ/
70 JEQ $ЕХ1Т
71 73 M2TR SET ENDW W2TR11
75 STCH M<UFADR,X ЗАПИСЬ СИМВОЛА В БУФЕР
180 TIXR 7 ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
85 JLT $LOOP ДЛИНЫ ЗАПИСИ
90 95 $CXIT STX MEND 6RECLTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
RDBUFF F2,BUFFER,LENGTH,(00,03,04 >
30 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
35 CLEAR A
47 +LDT 44096 МАКСИМАЛЬНАЯ ДЛИНА ЗАПИСИ = 4А96
50 SAALOOP TD =X'F2' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
'55 JEQ $AALOOP ЦИКЛ ОЖИДАНИЯ готовности
60 RD =X'F2/ ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
65 COMP =X'000000'
70 JEQ SAAEXIT
65 COHF* =X'000003'
70 JEQ SAAEXIT
65 COMP »X'000004'
70 JEQ SAAEXIT
75 STCH BUFFER,X ЗАПИСЬ СИМВОЛА В БУФЕР
80 TIXR. I ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
85 JLT $AAL00P ДЛИНЫ ЗАПИСИ
90 SAAEXIT STX LENGTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
б
Рис. 4.9. Использование предложений условного перехода периода макро-
генерации.
пор, пока некоторое условие является истинным. Как и рань-
ше, проверка этого условия и зацикливание осуществляются в
период макрогенерации. В проверяемых условиях могут исполь-
зоваться переменные периода макрогенерации и аргументы, но
не могут быть использованы значения, вычисляемые в период
выполнения программы.
Примером использования конструкции WHILE—ENDW яв-
ляются строки 63—73 на рис. 4.9а. Переменной периода макро-
генерации &EORCT предварительно (строка 27) было присвос-,
по значение % NITEMS (&EOR). %NITEMS - это макропроцес
сорная функция, значением которой является количество эле
ментов в списке, задаваемом в качестве аргумента этой <Ьупк
ции. Например, если значение аргумента, соответствующее па-
раметру EOR, есть (00, 03, 04), то значение %N1TEMS(&EORI
будет равно 3.
Переменная периода макрогенерацин &CTR используется
для подсчета того, сколько раз сгенерированы (перенесены из
тела макроопределения в результирующую программу) строки
следующие за предложением WHILE. Начальное значение&CTR
пола! ается равным 1 (строка 63) и далее увеличивается на 1
ЖЛ%ЖД0М ПрОХОДе "° ЦИКЛУ (строка 71). Само предложение
WHILE говорит о необходимости повтора цикла периода мак-
рогенерации до тех пор, пока значение переменной &CTR мень-
ше или равно значению переменной &EORCT. Это означает,
что строки 65—70 будут сгенерированы для каждого элемента
списка. Переменная &CTR используется в качестве индекса
для выборки соответствующего элемента списка. На первой
итерации выражение &EOR[&CTR] в строке 65 будет иметь
значение 00, на второй итерации — значение 03 и т. д.
На рис. 4.96 изображено расширение предложения макро-
инициализации с использованием макроопределения на
рис. 4.9а. Вы должны тщательно проанализировать этот пример
для того, чтобы убедиться, что вы правильно понимаете смысл
предложения WHILE.
Реализация цикла WHILE периода макрогенерацин также
достаточно проста. Когда макропроцессор встречает предложе-
ние WHILE, он вычисляет соответствующее булевское выраже-
ние. Если оно ложно, то макропроцессор пропускает строки в
таблице DEFTAB до предложения ENDW и продолжает далее
работать, как обычно, в режиме безусловной макрогенерацин.
Если же это выражение истинно, то макропроцессор продолжа-
ет обрабатывать строки таблицы DEFTAB обычным образом до
предложения ENDW. По предложению ENDW макропроцессор
возвращается к предложению WHILE, перевычпеляег соот-
ветствующее булевское выражение и действует далее в соответ-
ствии с этим новым вычисленным значением так, как уже опи-
сано.
Предложенный метод реализации не допускает вложенных
конструкций WHILE. Вы можете подумать над тем, каким а.
горитмом могут поддерживаться такие вложенные констр\ки -
(см. упр. 4.2.12).
4.2.4. Ключевые макропараметры
Все предложения макроинициализации, с которыми мы им^
ли дело до сих пор, имели позиционные параметры, т. с.
ветствие формальных параметров и аргументов осуществим
посредством соотнесения их позиций в макропрототипе и »
предложении макроинициализации. Используя позиционные пЛ
раметры, программист должен очень внимательно следить за
правильным порядком следования аргументов. Если некоторый
аргумент должен быть опущен, то предложение макроинициа-
лизации должно содержать пустой аргумент (две подряд иду-
щие запятые) для сохранения соответствия между аргументами
и параметрами. (См., например, предложение макронннниали-
зации на рис. 4.8в.)
Позиционные параметры вполне приемлемы для большин-
ства макроинструкций. Однако если макрос имеет большое
число параметров, а в типичном предложении макропнициали-
зации используются только некоторые из них, то для определе-
ния этих параметров может быть более удобной другая, непо-
зиционная форма записи. Такого рода макросы могут возникать
в ситуациях, когда результатом расширения одного предложе-
ния макроинициализации является большая и сложная после-
довательность предложений (может быть, даже вся операцион-
ная система). В подобных случаях большинству параметров
можно присвоить приемлемые значения по умолчанию, а в
предложении макроинициализации задать только те из них,
значения которых отличаются от принятых по умолчанию.
Предположим, например, что некоторая макроинструкция
GENER имеет 10 возможных параметров, но при ее инициали-
зации должны быть заданы только третий и девятый парамет-
ры. Соответствующее предложение макроинициализации будет
выглядеть следующим образом:
GENER „DIRECT,,, ,„3.
При использовании параметров другого типа, называемых клю-
чевыми, значение каждого аргумента записывается вместе с
ключевым словом, которое является именем соответствующего
параметра. Аргументы в этом случае могут записываться в лю-
бом порядке. Если предположить, что третий параметр в пре-
дыдущем примере имеет имя &TYPE, а девятый — имя
&CHANNEL, то предложение макроинициализации будет вы-
глядеть так:
GENER TYPE = DIRECT, CHANNEL =3
Это предложение гораздо легче читается и содержит потенци-
ально меньше ошибок, чем его позиционный вариант.
На рис. 4.10а изображен вариант макроса RDBUFF с ис-
пользованием ключевых параметров. За исключением способа
записи, все параметры те же, что и на рис. 4.8а. В макропро-
тотипе после каждого имени параметра следует знак равенства,
являющийся признаком ключевого параметра. После знака равен-
ства идет значение соответствующего параметра, принимаемое
25 пппигг млеко MWEV-rf ,Ш1ГЛПР-,ЛРГП ТИ-ДГПП-ЙЛ 1.МЛХ1.ТН -'П}У6 •
26 IF <6L0R NE ' ')
27 ♦EORCK SET 1
28 ENDIF
30 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
35 CLEAR A
38 IF <6EORCK EQ 1)
40 LDCH -X'&EOR' УСТАНОВКА СИМВОЛА EOR
42 RMO A,S
АЗ ENDIF
А7 +LDT ♦6MAXLTH УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
50 $LOOP TD =X'6INDEV' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
55 JEQ SLOOP ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
60 RD ~X'&INDEV' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
63 IF (6E0RCK EQ 1)
65 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
70 JEQ $EXIT ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
73 ENDIF
75 STCH 6BUFADR,X ЗАПИСЬ СИМВОЛА В БУФЕР
80 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
85 JLT SLOOP ДЛИНЫ ЗАПИСИ
90 $ЕХ1Т STX 6RECLTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
95 1 MEND
RDBUFF BUFADR=BUFFER,RECLTH=L£NGTH
30 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
35 CLEAR A
40 LDCH =X'04' УСТАНОВКА СИМВОЛА EOR
42 RMO A,S
47 +LDT ♦ 4096 УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
50 JAALDOP TD =X'F1' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
55 JEQ tAALOOP ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
60 RD =X'F1' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
65 COMPR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
70 JEQ lAAEXIT ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
75 STCH BUFFER,X ЗАПИСЬ СИМВОЛА В БУФЕР
80 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
£5 JLT $AALOOP ДЛИНЫ ЗАПИСИ
90 SAAEXIT STX LENGTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
6
RDBUFF RECLTH=LENGTH,BUFADR=BUFFER,EDR=,INI'EV=F3
30 CLEAR X
35 CLEAR A
47 +LDT ♦4096
50 tABLOOP TD «=X'F3Z
55 JEQ $ABLOOP
60 RD «=X'F3Z
75 STCH BUFFER,X
80 TIXR T
85 JLT $ABLOOP
90 $ABEXIT SIX LENGTH
ОЧИСТКА СЧЕТЧИКА ЦИКЛА
УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
ЗАПИСЬ СИМВОЛА В БУФЕР
ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
ДЛИНЫ ЗАПИСИ
СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
по умолчанию. Считается, что параметр поииим™
значение, если его имя не встретилось в ЦшХ это
предложения макроинициализации. В нашем" ппим₽ЛРГуМе,П0п
параметра &INDEV принимается равным Н a S
&BUFADR значение по умолчанию не определено* паРаметРа
Определение значений некоторых параметров по умопчт
пню во многих случаях упрощает макроопределение Напп^Д'
оба макроопределения на рис. 4.10а и рис. 4.8а прсдусматпив!:
ют установку максимальной длины записи равной 4096 сети
пользователь не задал другого значения. Если задано значение
по умолчанию, как на рис. 4.10а, то эти действия выполняются
автоматически. Для выполнения этих же действий в макро-
определении на рис. 4.8а понадобилась конструкция IF—
-ELSE—ENDIF.
Другие фрагменты рис. 4.10 содержат примеры макрорас-
ширений предложения макроинициалнзации с ключевыми пара-
метрами. На рис. 4.106 все параметры имеют значения, задан-
ные по умолчанию. На рис. 4.10в формальному ключевому
параметру &INDEV соответствует значение F3, а значением па-
раметра &EOR задана пустая строка. Значения, заданные для
этих параметров по умолчанию, игнорируются. Обратите вни-
мание, что аргументы в предложении макроинициалнзации мо-
гут быть расположены в любом порядке. Имеет смысл внима-
тельно проследить на этих примерах использование заданных
по умолчанию параметров.
4.3. Варианты построения макропроцессоров
В этом разделе мы обсудим некоторые базовые варианты
построения макропроцессоров. Представленный на рис. 4.5
алгоритм не сработает, если внутри тела макроопределения
встретится предложение макроинициалнзации. Часто, однако,
желательно использовать макросы именно таким образом.
В разд. 4.3.1 изучается эта проблема и предлагаются некото-
рые пути ее решения.
Хотя подавляющее большинство макросредств используется
в связи с программированием на языке ассемблера, имеются
также и другие приложения. В разд. 4.3.2 обсуждается макР°
процессор общего назначения, не связанный ни с каким к
кретным языком программирования. В разд. 4.4 приведен при-
мер подобного макропроцессора. В разд. 4.3.3 обсуждается др\
гая сторона того же вопроса: интеграция макропропсусор.
с конкретным ассемблером или компилятором. Мы о’суд
Рис. 4.10. Использование ключевых параметров.
23 26 RDBUFF macro IF (&LOR NE ' KWAnp-.MJFH ТИ-ДГЛГМТ ДМАХЕТН-АФУЙ >
27 4.EORCK SET 1
28 END IF
30 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
35 CLEAR A
38 IF (&EORCK EQ 1)
40 LDCH =X4EORZ УСТАНОВКА СИМВОЛА EOR
42 RMO ArS
43 ENDIF
47 Sloop ♦LDT ♦&MAXLTH УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
50 TD =X4 INDEV' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
55 JEQ SLOOP ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
40 RD -X'MNDEV' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
63 IF (&EORCK EQ 1)
65 COMER A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
70 JEQ SEX IT ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
73 ENDIF
75 STCH &BUFADR,X ЗАПИСЬ СИМВОЛА В БУФЕР
80 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
85 $ЕХ1 Г JLT SLOOP ДЛИНЫ ЗАПИСИ
90 STX ARECLTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
95 > MEND
RDBUFF DUFADK-BUFFER,RECLTH=LENGTH
30 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА
35 CLEAR A
40 LDCH ~XZ04Z УСТАНОВКА СИМВОЛА EOR
42 RMO A,S
47 4LDT ♦4096 УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
50 SAALOOP TD ^X'F1Z ПРОВЕРКА ГО(ОВНОС1И УСТРОЙСТВА
55 JEQ SAALOOP ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
60 RD -XzFlr ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
65 COMFR A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ
70 JEQ $AAEXIT ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ
75 STCH BUFFER,X ЗАПИСЬ СИМВОЛА В БУФЕР
80 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
85 JLT $AALOOP ДЛИНЫ ЗАПИСИ
90 SAAEXIT STX LENGTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
6
RDBUFF RECLTH=LENGTH,BUFADR=DUFFER,E0R*,INDEV=F3
30 CLEAR X
35 CLEAR A
47 4LDT ♦4096
50 tABLOOP TD *x'F3'
55 JEQ SABLOOP
60 RD t=X'F3'
75 STCH BUFFER,X
80 TIXR T
85 JLT SABLOOP
90 $ABEXIT STX LENGTH
ОЧИСТКА СЧЕТЧИКА ЦИКЛА
УСТАНОВКА МАКСИМАЛЬНОЙ ДЛИНЫ ЗАПИСИ
ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА
ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ
ЧТЕНИЕ СИМВОЛА В РЕГИСТР А
ЗАПИСЬ СИМВОЛА К БУФЕР
ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ
ДЛИНЫ ЗАПИСИ
СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ
по умолчанию. Считается, что папяммг.
значение, если его имя не встретилось' в cnnciTXT 8Т°
предложения макроинициализацип. В нашем mL? У е“тов
параметра &INDEV принимается равным Н 7 Тппп:1’'еиис
&BUFADR значение по умолчанию не определено ' араметРа
Определение значений некоторых параметров по умоли-,
Пию во многих случаях упрощает макроопределение Наппимоп
оба макроопределения на рис. 4.10а и рис. 4.8а предусматпива’
ют установку максимальной длины записи равной 4096 если
пользователь не задал другого значения. Если задано значение
по умолчанию, как на рис. 4.10а, то эти действия выполняются
автоматически. Для выполнения этих же действий в макро-
определении на рис. 4.8а понадобилась конструкция И- —
-ELSE—ENDIF.
Другие фрагменты рис. 4.10 содержат примеры макрорас-
ширений предложения макроинициализации с ключевыми пара-
метрами. На рис. 4.106 все параметры имеют значения, задан-
ные по умолчанию. На рис. 4.10в формальному ключевому
параметру &INDEV соответствует значение F3, а значением па-
раметра &EOR задана пустая строка. Значения, заданные для
этих параметров по умолчанию, игнорируются. Обратите вни-
мание, что аргументы в предложении макроинициализации мо-
гут быть расположены в любом порядке. Имеет смысл внима-
тельно проследить па этих примерах использование заданных
по умолчанию параметров.
4.3. Варианты построения макропроцессоров
В этом разделе мы обсудим некоторые базовые варианты
построения макропроцессоров. Представленный на рис. 4..
алгоритм не сработает, если внутри тела макроопределения
встретится предложение макроинициализацип. lacro, однак ,
желательно использовать макросы именно таким ооразсн.
В разд. 4.3.1 изучается эта проблема и предлагаются чеки
рые пути ее решения. ,„ЭТся
Хотя подавляющее большинство макросредств ,,с u -
в связи с программированием на языке ассем л [ <, _
также и другие приложения. В разд. 4.3.- обсужд< м н.
процессор общего назначения, не связанный ни н п
кретным языком программирования. В Раз^- .;Сужтается дру-
мер подобного макропроцессора. В разд. 4.3. J-попооцессора
гая сторона того же вопроса: «"те1Ра™я пмакрм°"Р
с конкретным ассемблером или компиля р
Рис. 4.10. Использование ключевых параметров.
возможности кооперации между макропроцессором и тоансп
тором и укажем на потенциальные преимущества и проблемы
которые возникают при такой интеграции. " 1 ы’
4.3.1. Рекурсивная макрогенерация
На рис. 4.3 был представлен пример определения одной
макроинструкции внутри другой. Мы, однако, не встречались с
тем, чтобы внутри тела макроопределения были предложения
макроинициалнзации. На рис. 4.11 представлен пример подоб-
ного использования макросов. Макроопределение RDBUFF на
рис. 4.11а в основном то же, что и на рис. 4.1. Для наглядности
изменен только порядок параметров. В этом примере мы
предполагаем, что макроопределение RDCHAR уже описано. Его
функцией является чтение одного символа с заданного устрой-
ства в регистр А с учетом необходимых проверок готовности
устройства. Соответствующее макроопределение изображено па
рис. 4.116. Использование макроса, подобного RDCHAR, весьма
удобно при определении макроса RDBUFF. Оно позволяет про-
граммисту при написании макроса RDBUFF не заботиться о
деталях управления и доступа к устройству. (Макрос RDCHAR
мог быть написан в другое время или даже другим програм-
мистом.) Использование такого макроса даст еще большие
преимущества на более сложной машине, на которой чтение
одного символа осуществляется более длинной и сложной, чем
в нашем случае, программой. К сожалению, изложенный выше
алгоритм работы макропроцессора не позволяет обрабатывать
инициализации макросов внутри других макросов. Предполо-
жим, например, что алгоритм на рис. 4.5 обрабатывает предло-
жение макроинициалнзации на рис. 4.11 в. После того как пред-
ложение макроинициализации будет распознано, будет вызвана
процедура EXPAND. Аргументы из предложения макроинициа-
лизации будут помещены в таблицу ARGTAB, как это изобра-
жено на рис. 4.11г. Булевской переменной EXPANDING будет
присвоено значение TRUE, и начнется процесс макрорасшире-
ния. Он будет протекать правильно до строки 50, содер/кашеи
инициализацию макроса RDCHAR. В этом месте процедура
PROCESSLINE обратится к процедуре EXPAND еще раз. 1ао-
лица ARGTAB будет преобразована к виду, представленному
на рис. 4.11д. Расширение макроса RDCHAR также 0С^Н11ССТВ11
ся правильно, однако после этого возникнут трудности. 1 ю koi
макроопределения RDCHAR переменной EXPANDING будет*пр
своено значение FALSE. Таким образом, макропроцессор «. <
дет», что он находился в середине процесса макрорасшир
Рис. 4.11. Пример вложенных макроинициалнзации.
? предложение инициализации макроса
YRDR n?F»K₽0Me Т0Г°’ аРгУмеНть' пеРвой макроиннциализацщ,
таблице АР?т\3иЛИСЬ ПОТСРЯННЫМИ> поскольку их значения в
RDCHARARGTAB Затерлись новым» аргументами макроса
Основной причиной этих трудностей является рекурсивный
вызов цроцедуры EXPAND. Сначала она будет вызвана при об-
работке предложения макроинициализации макроса RDBUFF
Далее она вызывает процедуру PROCESSLINE (строка 50)'
которая делает еще одно обращение к EXPAND до возврата
из первого вызова этой процедуры. Те же трудности возникнут
и с процедурой PROCESSLINE, поскольку она также вызыва-
ется рекурсивно. Например, возникает вопрос, куда передавать
управление после конца работы процедуры PROCESSLINE: в
основной цикл работы макропроцессора или же в цикл внутпи
процедуры EXPAND.
Эти трудности легко разрешимы, если макропроцессор пи-
шется на языке программирования, допускающем рекурсивные
вызовы (таком как Паскаль или ПЛ/1). Сам компилятор по-
заботится о том, чтобы значения всех переменных, определен-
ных внутри процедуры, были сохранены при рекурсивном об-
ращении. Компилятор позаботится также и о других деталях
обработки рекурсивных вызовов, включая определение адреса
возврата из процедуры. (В гл. 5 мы детально обсудим, как
компилятор обрабатывает подобные рекурсивные вызовы.) Если
же допускающий рекурсию язык программирования недоступен,
то программист обязан сам позаботиться о таких вещах, как
адрес возврата и значения локальных переменных. В этом слу-
чае PROCESSLINE и EXPAND, может быть, вообще не будут
оформлены как процедуры. Вместо этого та же логика работы
может быть реализована с помощью операторов цикла с хра-
нением значений переменных в стеке. Используемые здесь ме-
тоды реализации описаны в гл. 5 при обсуждении рск> Iй
Пример подобной реализации содержится в район Дошл-
[1972].
4.3.2. Макропроцессоры общего назначения
Наиболее часто макропроцессоры используются при npoipa^
мировапии на языке ассемблера. Часто такие макр > орь1
встроены в ассемблер. Специализированные мам ;I ания
были созданы также для некоторых языков ПР? Р * _ 11976].)
высокого уровня, (См., например, Керниган и ла ,1иаЛогич-
Эти специализированные макропроцессоры во мн <. ' по;1.
ны с точки зрения выполняемых функции и ис1’°^ ями Кон-
хода. Их различия связаны в основном °собенн
кретного языка программирования. В этом раздел
дим макропроцессоры общего назначения Они пп « ~---
какого конкретного языка программирования и „В"СЯТ,,Иог
использованы с целым рядом различных языков Ппо°ГуТ быть
такого общего подхода к построению макропроцессоров™3
ны. Программист не должен изучать специал^.^»* Очевид-
росредства для каждого компилятора или языка МаК‘
В результате экономится много времени и средств ппи’об?3’
нии. Стоимость разработки макропроцессора общего Хачения
несколько больше по сравнению со специализированными мак
ропроцессорами. Однако эти затраты не будут повторяться тля
каждого языка. Результатом будет существенное сокращений
общих затрат на разработку и сопровождение математического
обеспечения. На протяжении ряда лет экономия на сопровож-
дении меже! превысить первонэчзльные затраты на разработ-
ку математического обеспечения.
Несмотря на все эти преимущества, в настоящее время име-
ется сравнительно мало макропроцессоров общего назначения.
Одна из причин подобного положения дел связана с огромным
количеством деталей, которые необходимо иметь в виду при
программировании на любом реально используемом языке. Эти
многочисленные детали могут быть встроены внутрь специали-
зированного макропроцессора. Макропроцессор же общего на-
значения должен предоставлять пользователю средства, позво-
ляющие ему самому определить необходимый набор правил,
которому должен следовать макропроцессор.
При работе с обычными языками программирования
встречается несколько ситуаций, в которых обычная подстанов-
ка макропараметров не должна осуществляться. Например, ком-
ментарии, как правило, игнорируются макропроцессором (по
крайней мере при обработке списка параметров). Каждый язык
программирования имеет свои
тификации комментариев. Они
мощью ключевых слов (как в
циальных символов в начале
собственные средства для идеи-
могут идентифицироваться с по-
Алголе) или же с помощью спе-
и в конце комментария (как в
например Фортран, используют
Паскале). Некоторые языки,
специальный символ, означающий, что вся строка является ком-
ментарием. В большинстве языков ассемблера любые символы
в строке, следующие за полем операнда, автоматически рас
сматриваются как комментарии. В некоторых языках неволь
зуется специальный символ разделитель. Все символы, *
щиеся после него в строке, рассматриваются как комме < | .
Другие различия между языками программирования с
со средствами группирования отдельных элементов ’
ражений или предложений. Большинство язь1^в /оби1е.
для этого скобки. В некоторых случаях макропроцес р)
го назначения будет необходимо знать средподобно
группирования при сканировании исход
символы вместо
ИС-
Однако некоторые языки используют другие С « I»» ии. I IM UMt
круглых скобок (например, символы ( и )). Некоторые языки
пользуют для этих целей ключевые слова begin и end.
Более общая проблема состоит в структуре лексем языка
программирования, например идентификаторов, констант, опе-
раторов, ключевых слов. Языки существенно различаются по
ограничениям, которые они накладывают на длину идентифика-
торов и правила написания констант. В некоторых случаях пра-
вила построения подобных лексем различны в разных частях
программы (например, в предложении FORMAT языка Фор-
тран или в предложении DATA DIVISION в языке Кобол).
В некоторых языках имеются операторы, записываемые не-
сколькими символами, такие как ** в языке Фортран и := в
Паскале. Если макропроцессор будет воспринимать их как два
независимых символа, а не как один оператор, могут встретить-
ся определенные трудности. Даже формат записи предложений
исходной программы во входном файле может привести к
определенным трудностям. Макропроцессор должен учитывать,
являются ли пробелы разделителями или должны полностью
игнорироваться, способы записи одного предложения в несколь-
ких строках, специальные соглашения по форматированию пред-
ложений, подобные принятым в языках Фортран и Кобол.
Другая проблема, которая может возникнуть при разработ-
ке макропроцессора общего назначения, связана с синтаксисом
предложений макроопределения и макроинициализации. Для
большинства специализированных макропроцессоров предложе-
ния макроинициализацип весьма похожи на другие предложе-
ния базового языка программирования. (Например, инициали-
зация макроса RDBUFF на рис. 4.1 имеет ту же форму, что и
предложение на языке ассемблера УУМ.) Эта схожесть форм
имеет целью облегчить написание и чтение программ. Этого
трудно достичь для макропроцессора общего назначения, кото-
рый предназначен для работы с языками программирования,
имеющими различный формат предложений.
В разд. 4.4.3 мы кратко опишем макропроцессор общего на-
значения, в котором решены многие из перечисленных выше
вопросов. Обсуждение макропроцессоров общего назначения и
макропроцессоров для языков программирования высокого уров-
ня содержится в работах Коул [1981], Браун [19/4] и Кэмп-
бел-Келли [1973].
4.3.3. Макропроцессоры, встроенные в
трансляторы
Все обсуждавшиеся до сих пор макропроцессоры могут быть
названы препроцессорами. Они обрабатывают макроопределе-
ния и предложения макроинициализации, генерируя расширен-
ную версию исходной программы. Эта расширенная программа
далее используется в качестве входной для ассемблера или
компилятора. В этом разделе мы обсудим другую альтернати-
ву-реализацию функций макропроцессора ’ самим трансля-
тором.
Простейший способ достижения подобного объединения со-
стоит в использовании принципа «строка за строкой». В этом
случае макропроцессор читает предложение исходной про-
граммы и выполняет все описанные выше функции. При этом
строки, сгенерированные макропроцессором, передаются на вход
транслятора по мере того, как они генерируются (последова-
тельно одна за одной), вместо того, чтобы писать расширенную
программу в файл. В этом случае макропроцессор выполняет
функции, аналогичные подпрограмме чтения очередной строки
для ассемблера или компилятора.
Подобный подход имеет несколько преимуществ. Он позво-
ляет избежать дополнительного прохода по программе (записи
ее в промежуточный файл и последующего чтения) и в резуль-
тате может быть более эффективным, чем использование мак-
ропроцессора. Некоторые таблицы, требующиеся и макропроцес-
сору, и транслятору, могут быть объединены. Например, таблица
ОВТАВ в ассемблере и таблица NAMTAB в макропроцес-
соре могут быть реализованы в виде одной таблицы. Кроме
того, многие вспомогательные программы и функции могут ис-
пользоваться как транслятором, так и макропроцессором. Сюда
относятся операции сканирования входной строки, поиска по
таблицам, преобразование числовых констант из внешнего во
внутреннее представление. В рамках этого подхода облегчается
привязка диагностических сообщений к предложению исходной
программы, вызвавшей ошибку (т. е. к соответствующему пред-
ложению макроинициализации). При использовании макропре-
процессора подобная ошибка может быть отнесена только к
соответствующему предложению макрорасширения. Програм-
мист будет в этом случае самостоятельно искать исходную при-
чину ошибки.
Хотя макропроцессор, реализующий принцип «строка за
строкой», и может использовать те же подпрограммы, что и
транслятор, по-прежнему его функции и функции транслятора
остаются существенно различными. Основной формой связи ме-
жду ними является передача предложений программы с выхода
одного на вход другого. Однако можно себе представить еще
более тесное взаимодействие между макропроцессором и ас-
семблером. Речь идет о макропроцессоре, встроенном в транс-
лятор.
Встроенный макропроцессор потенциально может использо-
вать любую информацию об исходной программе, имеющеюся >
транслятора. Объем этой информации существенно различаете
в разных системах. При относительно простом варианте
взаимодействия макропроцессор использует такие операции
транслятора, как сканирование, обработка констант и т. д. Эти
операции в любом случае должны осуществляться компилято-
ром или ассемблером; макропроцессор просто использует их
результаты, не вдаваясь в такие детали, как изображение од-
ной операции языка несколькими символами, расположение од-
ного предложения языка на нескольких строках, формат лек-
сем и т. п. Это особенно важно в тех случаях, когда эти пра-
вила различаются в разных частях программы (например,
внутри операторов FORMAT и символьных констант языка
Фортран).
Сканирование лексем, о котором только что шла речь, кон-
цептуально очень просто. Однако многие существующие языки
программирования имеют особенности, доставляющие опреде-
ленные трудности и на этом этапе. Классическим примером яв-
ляется предложение Фортрана
DO ЮО 1 = 1,20
Это оператор цикла DO, где DO распознано как ключевое сло-
во, 100 — метка предложения, I — имя переменной и т. д. По-
скольку пробелы никак не учитываются в предложениях Фор-
трана (кроме символьных констант), похожее предложение
DO 100 1=1
имеет совершенно другой смысл. Это оператор присваивания пе-
ременной DO 1001 значения 1. Таким образом, правильная ин-
терпретация термов DO, 100, 1 не может быть осуществлена до
тех пор, пока не проведен анализ всего предложения. 1акая
интерпретация будет очень важна, например, в случае, если
макропроцессор должен заменить переменную с именем 1. Ком-
пилятор с Фортрана обязан разбираться с подобными ситуация-
ми. Однако для обычного макропроцессора (не встроенною в
компилятор) это сделать очень трудно. Такой макропроцессор
может иметь дело с предложениями исходной программы ю.пж 1
как со строками символов, не имея возможности выделить их
отдельные элементы.
При более тесной связи с транслятором встроенный макро-
процессор может обрабатывать макроинструкции, смысл кото-
рых зависит от того контекста, в котором они оказались На-
пример, с помощью такого макроса можно задать замену имен
только переменных или констант определенного типа лит
только переменных, являющихся переменными цикла в пред-
ложениях DO. Процесс макрогенерации может также зависеть
от множества характеристик аргументов предложения макро-
инициализации. (Примером может служить описание макропро-
цессора System/370 в разд. 4.5.1.)
Макропроцессоры, тесно связанные с транслятором, име-
ют, конечно, и свои недостатки. Они должны быть спроектиро-
ваны специально для работы с конкретной реализацией некото-
рого ассемблера или компилятора (а не просто для работы с
языком программирования). Стоимость разработки такого мак-
ропроцессора должна быть прибавлена к стоимости разработки
транслятора, что приводит к более дорогим компонентам мате-
матического обеспечения. Кроме того, ассемблер или компиля-
тор становится больше и сложнее, чем это было бы в случае
использования макропрепроцессора. Размер транслятора может
представлять собой проблему, если транслятор предназначен
для работы на ЭВМ с ограниченной оперативной памятью.
В любом случае увеличиваются накладные расходы па тран-
сляцию. (Некоторые ассемблеры со встроенными макропроцес-
сорами требуют больше времени на обработку одной строки ис-
ходной программы, чем некоторые компиляторы на той же са-
мой ЭВМ.) Решение вопроса о типе макропроцессора, который
должен использоваться, опирается на данные о предполагае-
мой частоте и сложности макрогенерации и другие характери-
стики операционного окружения.
4.4. Примеры реализации
В этом разделе мы кратко опишем три реальных макропро-
цессора. Как и раньше, не будем пытаться охватить вес харак-
теристики каждой системы, а сосредоточимся па наиболее ин-
тересных особенностях. Первые два примера посвящены макро-
процессорам, тесно связанным с ассемблером (для System/370
и ЭВМ серии VAX). Третий пример — макропроцессор общего
назначения, предназначенный для использования в качестве
препроцессора с самыми различными языками программиро-
вания.
4.4.1. Макропроцессор System/370
Рассматриваемый в этом разделе макропроцессор Sy-
stem/370 тесно связан с ассемблером этой системы. Он ооес-
печивает все функции макропроцессора, которые мы обсужда-
ли, включая обработку макроопределений и макроиницпализа-
ций внутри тела макроопределения. В микроинструкциях мог> г
использоваться позиционные или ключевые параметры лиио
смесь позиционных и ключевых параметров. Управляющие пред
ложепия позволяют пользователю задавать различные режимы
работы макропроцессора, например разрешить или 3aril’eIlirl’
появление предложений текста макрорасширения в лист
исходной программы. Комментарии в теле макроопределс
могут игнорироваться, а могут и остаться в листинге ассембло
ра в зависимости от способа их записи.
Существенное отличие макропроцессора System/370 от пас.
смотренного нами макропроцессора для УУМ состоит в ctdvk.
туре предложений условной макрогенерации. В макроязыке для
bystem/3/О они называются предложениями условного ассембли-
рования. Хотя эти предложения и предназначены в основном
для макрогенерации, они могут появиться также и вне макпо
определений. Язык ассемблера System/370, дополненный опера-
торами условного ассемблирования, допускает использование
переменных периода ассемблирования, которые аналогичны об-
суждавшимся выше переменным периода макрогенерации Этим
переменным могут быть присвоены арифметические, двоичные
или символьные значения. Этим трем типам значений соответ-
ствуют три типа таких переменных. Переменные периода ассем-
блирования могут быть как локальными, так и глобальными. Па
локальные переменные можно ссылаться только внутри того
макроопределения или такой подпрограммы на ассемблере, ко-
торые содержат их определения. Если локальные переменные,
имеющие одно имя, будут определены в нескольких макроопре-
делениях, то транслятор будет рассматривать их как различные
переменные. Глобальные переменные могут использоваться в
любом месте программы. Так, например, глобальной перемен-
ной может быть присвоено значение в момент обработки одного
макроса, а использоваться это значение может в другом мак-
росе.
Предложения условного ассемблирования, управляющие по-
рождением строк результирующей программы, существенно от-
личны от условных предложений периода макрогенерации для
УУМ. Базовой управляющей конструкцией является оператор
перехода периода ассемблирования. При выполнении такого
перехода ассемблер (или макропроцессор) прерывает последо-
вательную обработку предложений программы и в качестве
очередного предложения берет то, которое указано в операторе
перехода. Эти переходы могут быть как «вниз», так и «вверх»
по входному потоку.
На рис. 4.12 изображены примеры макроопределения и тек-
ста макрорасширения с использованием макроязыка Ь\-
stem/370. Это макроопределение предназначено для генерации
кода, осуществляющего сложение дву,х элементов данных п 1 3<_
поминание результата. В зависимости от типа аргументов
целые или с плавающей точкой — порождается различный к . •
Если аргументы имеют какой-либо другой или не совпала кии'
между собой тип, то генерируется сообщение об ошибке. <-|
ма макроопределения на рис. 4.12а в основном та же, что и
наших предыдущих примерах. Макроопределение иач,'1'|'\Л
предложением MACRO и заканчивается предложением / н -
1 MACRO
2 &NAME ADD AOPl ,iOP2,J.SUM
3 LCLC ATYPE
4 5 AIF AIF <T4OP1 NE T'1OP2) .MIXTYP (ТЧ0Р1 EQ 'F'> .INT№
6 AIF (ТЧОР1 EQ 'E') •FLOAT
7 AGO -TYPERR
8 .FLOAT ANOP
9 &TYPE SETC 'E'
10 •INTGR ANOP
11 &NAME L&TYPE 2?&0Pi
12 A6TYPE 2,&0P2
13 ST&TYPE 2,*<SUM
14 MEXIT
15 •MYXTIP MNOTE 'СМЕШАННЫЕ ТИПЫ ОПЕРАНДОВ'
16 MEXIT
17 18 .TYPERR MNOTE MEND 'НЕДОПУСТИМЫЙ ТИП ОПЕРАНДОВ
LAB ADD IrJrK
4
LAP L 2,1
A 2,J
ST 2,К
ADD
LE
AE
STE
X,Y,Z
2, X
2,Y
2,Z
в
ADD I,Y,Z
jf*** СМЕШАННЫЕ ТИПЫ ОПЕРАНДОВ
рис. 4.12. Примеры макроопределения и макрорасширений для System 3/0
------ г . MIXTYP — Прим, персе,
В строке 15 рис. 4.12 имя метки должно быть Ml
Макропрототип расположен сразу же за предложением MACRO
(строка 2). Все макропараметры и переменные периода ассемб-
лирования начинаются символом &. В этом примере исполь-
зуются только позиционные параметры.
Предложение LCLC в строке 3 определяет переменную
&11РЕ строкового типа. Эта переменная определена как ло-
кальная в том макроопределении, в котором она описана. По
умолчанию ей присваивается начальное значение — пустая
строка. Предложение в строке 4 (AIF) является предложением
условного перехода периода ассемблирования. Ассемблер вы-
числяет булевское выражение в скобках и переходит на обра-
ботку другого места исходной программы, если это выражение
истинно. В противном случае ассемблер продолжает обрабаты-
вать следующую строку исходной программы. В нашем примере
адрес перехода задается с помощью специальной метки
MIXTYP, которая описана в строке 15. Аргументами булевского
выражения в предложении AIF являются типы параметров
макроопределения. Тип параметра &ОР1 (обозначаемый
T'&OPl) есть символ F, если соответствующий параметр явля-
ется целой переменной длиной в одно слово, и символ Е, если
он является числом с плавающей точкой. Таким образом, пред-
ложение AIF в строке 4 определяет переход к строке 15, если
типы двух параметров различны. Если же их типы совпадают,
то ассемблер продолжает работу со строки 5. Другое пред-
ложение AIF имеет аналогичную структуру.
Предложение AGO в строке 7 является оператором безус-
ловного перехода периода ассемблирования, предложение
ANOP (строки 8 и 10) — пустым оператором. Эти предложения
используются для описания меток FLOAT и INTGR. В строках
14—17 содержатся макродирективы двух новых типов. Предло-
жение MNOTE вызывает печать сообщения об ошибке в лис-
тинге ассемблера. Реакция ассемблера на это сообщение будс,
такой же, как реакция на собственную ошибку. Предложение
MEXIT предписывает макропроцессору закончить процесс по-
рождения текста макрорасширения текущего предложенияi маи-
роинициализации, несмотря на то что предложение MEND ешс
не встретилось.
На рис. 4.126—г изображены предложения макроинициал и-
зации и соответствующие им макрорасширения. Предполагай
ся, что I, J и К являются целыми переменными длиной в однj
слово, а X, Y, Z — переменными с плавающей точкой.
убедиться, что вы правильно понимаете работу предложен^
A1F и AGO, вам необходимо проследить по шагам весь и Р1’
цесс макрогенерации, используя макроопределение на рис. 4.!-♦
В рассмотренном примере предложения AIF и AGO
чивают действия, эквивалентные конструкции IF— EL81
ENDIF. Поскольку цикл WHILE также может быть запроса
И AGO, ЭТИ сред.
асссмбдироваиия.
реализовывать (и
миров.)и с использованием предложений A1F
ства дают широкие возможности условного
Однако предложения Л1Е и AGO труднее
вообще говоря, менее удобно использовать) чом
JF и WHILE, используемые для УУМ. Предложения
макрогенерации для УУМ аналогичны управляющим \СЛОВИОИ
рам структурированного языка, подобного Паскалю ПредТже'
НИЯ условного ассемблирования в System/370 больше? похожи
на средства неструктурированного языка, такого
Фортран IV. и как
В примере на рис. 4.12 предложение A1F использовалось
для проверки типа макроаргументов. Имеется множество дру-
гих характеристик переменных и аргументов, которые могут
использоваться сходным образом. Эти характеристики называ-
ются атрибутами соответствующих переменных и аргументов.
В предложениях условного ассемблирования допустимо ссы-
латься на атрибуты объектов, определения которых еще не
встречались в исходной программе. В результате ассемблер
System/370 должен делать предварительный просмотр всей ис-
ходной программы, запоминая атрибуты всех объектов для их
возможного использования в предложениях условного ассемб-
лирования. Этот предварительный проход осуществляется до
обработки каких бы то ни было макроинструкций, поэтому не-
допустимо ссылаться на атрибуты объектов, которые будут
определены лишь в процессе макрогенерации.
Макропроцессор System/370 позволяет использовать ряд си-
стемных переменных. Можно считать, что они определены за-
ранее и поэтому могут использоваться при макрогенерации.
Примерами таких системных переменных могут служить текущая
дата, время работы ассемблера, имя текущего управляю-
щего раздела. Одна из системных переменных &SISNDX пред-
назначена для генерации уникальных меток. Значением пере-
менной &SISNDX является четырехразрядное целое число пер-
воначально равное 0001 и увеличивающееся на 1 при обратим кс
каждого предложения макроинициализацип. Использхя э
переменную в качестве составной части метки, прог
ж ст избежать дважды определенных меток. и т ъ при
L&S1SNDX может принять значения L0001, L0 " ' З'ацни
последовательной обработке предложении макРХт/370 садер-
Подробиая информация о макропроцессоре System/3/и 1
жится в IBM [1979] и IBM [1974].
4.4.2. Макропроцессор системы VAX
Макропроцессор системы VAX также: С11ЛЬП°ТО сам язык
семблером этой системы 11ас.т?.льД0 Ппинципы записи макро-
ассемблера назван VAX-11 и MACRO. Принцш
определений и предложений макроинициализации те же, что и
для УУМ, но есть и интересные отличия.
Имена параметров макроинструкций не обязаны начинаться
с & или какого-либо другого специального символа. В резуль-
тате процесс сканирования для обнаружения параметров услож-
няется. Кроме того, чаще должен использоваться оператор кон-
катенации. Рассмотрим в качестве примера макроопределение
на рис. 4.13а. В предложении
3 TSTL R'NUM
операндом является символ R, конкатенированный со значением
параметра NUM. Для обозначения операции конкатенации в
макроязыке системы VAX используется апостроф Если бы
этот операнд был записан просто как RNUM, то последователь-
ность символов NUM не была бы распознана в качестве мак-
ропараметра. Таким образом, оператор конкатенации тут совер-
шенно необходим. Сравните эту ситуацию с примером на
рис. 4.12. В строке 13 этого примера не требуется никакого опе-
ратора конкатенации при записи терма ST&TYPE, поскольку
амперсанд является признаком того, что &TYPE является па-
раметром. Вообще говоря, макропроцессор мог бы распознать
последовательность символов NUM на рис. 4.12 как имя пара-
метра без оператора конкатенации. Однако в этом случае мак-
ропроцессор должен был бы иметь средства, позволяющие за-
претить подстановку параметров (например, мы можем нс за-
хотеть, чтобы NUMBER было превращено в 5BER). Если же
макропараметр не сконкатенирован ни с какими другими сим-
волами, то апостроф, конечно же, не нужен.
Макропроцессор системы VAX также предоставляет средства
генерации уникальных локальных меток при макрогенерацин.
Программист описывает локальную метку, путем включения ее
в список параметров макроопределения, добавив предварительно
перед именем метки символ ?. Задав соответствующий аРг\;
мент в предложении макроинициализации, можно дать
метке произвольное значение. Если же оно не определено, т
ассемблер сгенерирует новую локальную метку. Метки, гид-
рируемые ассемблером, находятся в диапазоне 30000 ,$ — '>•'; '
Этот процесс проиллюстрирован макроопределением и..
рис. 4.13а, предложениями макроинициализации и соответств}
ющнми макрорасширениями на рис. 4.136—в. В первом макР''
расширении метка L1 заменена на 30000$; во втором
30001$. Программист может также определить локальные мет '
вне тела макроопределения (в предложении макроинициал и. *
ции). Однако, чтобы не было пересечений с метками, гс”еР
руемыми макросредствамн, документация ассемблера L-
чтобы метки пользователя не попадали в интервал 30001.
65535$. Вы можете сами проследить процесс получения маки
1
2
3
А
Б
L1:
•MACRO
SUB'SIZE'
TSTL
BGEO
mnegl
• ENDM
ABSDIF DPI,0P2,SIZE.NUM,?L1
OP1,0P2,R'NUM
R'NUM
LI
R'NUM.R'NUM
ABSDIF
.а
ABSDIF
ЗШЦ:
SUBL3
TSTL
BGEQ
MNEGL
X,Y,L,0
X,Y,R0
R0
30000$
R0,R0
3
б
ABSDIF
30001$
SUBW3
TSTL
JBGER
MNEGL
30001$
K2,R2
Рис. 4.13.
рии VAX.
Примеры макроопределения
и макрорасширений для ЭВМ ее-
I,J,R2
В
расширения на рис. 4.13, обращая внимание на
операторов конкатенации и локальных меток.
Дальнейшая информация о макропроцессоре
содержится в DEC [1972] и DEC [1979].
4.4.3. Макропроцессор общего назначения
использование
системы VAX
РМ
макропроцес-
(Pattern Mat-
В этом разделе мы дадим кРвтД°е'я^РМ
сора общего назначения, имею1Д той системы имеется в
ching). Более подробное описание этом
Сасс [1979]. ооыа маКооиницнализации мак-
Макроопределения и предложу * от рассмотренных
ропроцессора РМ сУщественн° <пОНов (макропрототипов), со*
ранее. Средства записи макро _ овкам макроопределении,
ответствующие по назначен! Ов. Некоторые части ш
имеют множество различных P могут содержать набор
лона могут быть вообще опущ > 1 повторяться столько 1 »
тернативных конструкции; м у огенерации инициализ»Р>^
сколько необходимо. пРоцессЛпГ) Р с некоторым фрагме
ся при совпадении макрошаблона с
входного текста. Предложение макроинициализации (и даже
его отдельные аргументы) может быть записано в нескольких
строках исходного файла. Язык записи тел макроопределений
похож на Алгол.
Макропроцессор допускает определение пользователем ло-
кальных и глобальных меток периода макрогенерацин. Имеются
также системные переменные периода макрогенерации, анало-
гичные тем, с которыми мы встречались при анализе макропро-
цессора System/370. Одна из таких системных переменных яв-
ляется счетчиком количества обработанных предложений мак-
роинициализации. Значение этой переменной может быть ис-
пользовано для генерации уникальных меток. Допустимы также
предложения условной макрогенерацин, которые функционально
(но не по способу записи) близки к условным предложениям
макроязыка УУМ.
Важной особенностью макропроцессора РМ является то,
что пользователь может определить ряд языково-зависимых
конструкций. Как мы уже говорили в разд. 4.4.2, учет спе-
цифики конкретного языка может представлять большие труд-
ности при реализации макропроцессора общего назначения.
Оператор skip этого макропроцессора является обобщением идеи
комментария. Он выделяет порции входного текста, которые не
обрабатываются или должны быть удалены. При этом пользо-
вателю предоставлена возможность определения синтаксиса
оператора skip. Возможно также потребовать замену вхожде-
ний операторов skip на некоторые заданные строки символов.
Оператор сору в РМ является обобщением идеи текстовой
константы, т. е. порции информации входного текста, которая
должна быть непосредственно скопирована в выходной текст
без анализа макропроцессором. Пользователь имеет возмож-
ность определить синтаксис оператора сору. Символы или лек-
семы, определяющие начало и конец копируемого куска текста,
могут быть изменены в выходном файле. В дополнение к опе-
раторам skip и сору макропроцессор РМ имеет средства опи-
сания количества открывающихся и закрывающихся скобок,
лексем, состоящих из нескольких символов, правила записи од-
ного предложения на нескольких строках, а также средства об-
работки пробелов и признака «конец строки».
На рис. 4.14 изображен пример макроопределения и п[н >
ложения макроинициализации для макропроцессора 1м. а
роопределение на рис. 4.14а разработано для использования
языком Фортран. Предложение макроинициализации по Ф°Р^
похоже на алгольное предложение for; выходной текст ими.
формат Фортрана. Строка 1 определяет шаблон предложи
макроинициализации: ключевое слово for, за которым слсд\^
параметр id, за которым следует ключевое слово from и г- •
Предложение, заключенное в скобки, определяет альтернат
1
2
3
4
5
6
7
8
9
10
11
macro 'for' id
begin
__________________________________217
from' f ('by' b I /) 'to' t 'do' body;noneg 'od'
<Xid = Xf
Xsnum IF (Xid .GT rd тп •/?
Xbody 60 T0
Xid = Xid + >;
if b * ' ' then
<X/GO TO Xsnum
<(Xb)>
else <1> fi;
XCsnum + 1) CONTINUE X/>?
snurn := snum + 7;
end
a
for I from 0 to n-1
do
S := S +
od
1=0
9000 IF (I .GT. N-1) GO 10 9001
S = S + A<I)
1 = 1 + 1
GO TO 9000
9001 CONTINUE
в
Рис. 4.14. Примеры макроопределения и макрорасширений для макропро-
цессора РМ.
иые варианты построения J
Выражение в скобках можс рукцию by. Таким образом
символом /), либо содержа > 4конструкция by ми/'
в предложении макроинициал на Спецификация поВ^’
либо содержаться, либо бь1ТВ У еделяет, что пробелы и с
следующая за параметром body, 'чИМЫМИ (т. е. не долм
волы «конец строки» являю оцачений макроаргумен' _
игнорироваться) при обрабог', _ алгольном СТ1,;1С ”111НРе-
iVo макроопределения зап,нсао М
ках 2—11. Текст, который должс оках 3-6 содср .
иии, заключен в угловые ско м • выходного те^ пере.
четыре строки выходного текс • У параметров и рока 3
вол % используется для вЫА Так, например, п ' 1саи0
менных периода макрогенер 'йл должно быть 1 т зна-
Говорит о том, что в выход' пства, за которым ‘ -н вХОд-
Ч за которым следует знак р коНЧается. Коней теКсте.
чение параметра 1. Далее строка кон । в выходном
него текста порождает «он^йСХода макрогенеради
предполагается, что переме!
ранее уже присвоено начальное значение 9000. Эта переменная
используется для генерации меток предложений Фортрана.
В результате обработки строки 7 в выходном тексте появится
либо значение параметра Ь, либо 1 в зависимости от того, был
ли задан аргумент, соответствующий параметру Ь. Его значе-
ние окажется на той же строке, которая начала образовываться
при обработке строки 6 макроопределения. Символы %/, ко-
торыми начинается строка 8, означают конец строки. Таким
образом, предложение GOTO будет расположено в отдельной
строке. Оператор присваивания в строке 10 увеличивает значе-
ние переменной snum периода макрогенерации таким образом,
что в следующем макрорасширении метки оператора Фортрана
не будут совпадать с ранее сгенерированными.
На рис. 4.146 изображено предложение, которое будет обра-
ботано как предложение макроинициализации только что
описанного макроопределения. На рис. 4.14в приведен сгенери-
рованный текст. (Детали,определяющие формат выходных фор-
трановских строк, опущены.) Предполагается, что было опреде-
лено соответствующее макроопределение, заменяющее символы
:= на символ = в операторе присваивания S:=S4-A(I). По-
дробно проанализируйте этот пример, чтобы лучше попять про-
цессы макроинициализации и макрогенерации, реализованные в
макропроцессоре РМ.
Упражнения
Раздел 4.1
1. Примените приведенный на рис. 4.5 алгоритм для обработки исход-
ной программы на рис. 4.1. Результат должен совпасть с изображенным на
рис. 4.2.
2. Предложение макроинициализации является частью исходной про-
граммы. Во многих случаях программист не интересуется предложениями
макрорасширения. Каким образом за счет взаимодействия макропроцессора
и ассемблера можно добиться того, чтобы в листинге ассемблерной ПР "
граммы были только предложения макроинициализацип и отсутствовали
предложения макрорасширения?
3. Предположим, мы хотим видеть макроопределения внутри асссмб. р-
пого листинга. Каким образом макропроцессор и ассемблер могут о.'
реализовать?
4. В большинстве случаев фрагменты комментариев не должны ' г [
пяться иа значения макроаргументов, даже если они и совпадают с ’’мс ‘ "'9
макропараметров. Каким образом можно предотвратить замену парам • р-•
внутри комментариев?
5. На основании чего программист должен принять решение о
зации некоторой конкретной логической функции с помощью подпрогр.
или макроопределения?
6. Напишите алгоритм работы двухпросмотрового макропроцессора.^,
торый при первом просмотре обрабатывает все макроопределения, а на
ром — предложения макроинициализации. Можно считать, что вложс
----------------------------Упражнс пн я
"v
чтобы макропроцессор бочч пп Ли иа рис* 4.5 алгооитм
из библиотеки. '* * гшса»ное программистом мзгппМ обРаз°м,
__ ^^определение
8. Предложите некоторый способ работы
NAMTAB.
с таблицами DEFTAB и
•L Предположим, что вхождения мя
не заменены соответствующими позиционн^Ж^.?0 в Ta6™ue DEFTAB
---лтл ПЛТ-ПлАглт П п г»гЛгч,,^..л OOO3H3 4QH11 ЯМ И K1VH
нения это потребует в алгоритме работьГмак^опроцёссор
а
на рис. 4.5?
Раздел 4.2
1. Макроопределение на рис. 4.1 содержит несколько предложений, в
которых макропараметры сконкатеиированы с другими символами (напри-
мер строки 50 и 75). Почему в этих предложениях нет необходимости ис-
пользовать оператор конкатенации?
2. Модифицируйте приведенный на рис. 4.5 алгоритм так, чтобы он
обрабатывал операторы конкатенации.
3. Модифицируйте приведенный на рис. 4.5 алгоритм так, чтобы предо-
ставить пользователю средства генерации уникальных меток при макро-
генерации.
4. Предположим, что мы хотим использовать метки внутри текста
макрорасширения, не требуя, чтобы они имели какую-либо специальную фор-
му (например, начинались символом %). Каждая такая метка предполагается
описанной только внутри соответствующего макрорасширения, что исклю-
чает проблему дважды определенных меток. Каким образом макропроцес-
сор и ассемблер должны взаимодействовать для обеспечения такой воз-
можности?
Б, В чем заключается наиболее существенное различие между следую-
щими фрагментами:
а) LDA ALPHA
COMP #0
JEQ SKIP
LDA # з
STA BETA
SKIP « *
б) IF (3ALPHA NE 0)
&ВЕТА SET 3
ENDIF
цИа ’ П°ЛуЧНТе макР°РасшиРения следующих двух предложений макропнн-
лизации, используя макроопределения, приведенные на рис. 4.8а
‘а) RDBUFF F1, BUFFER, LENGTH, 00,1024
б) LOOP RDBUFF F2,BUFFER,LTH
Модифицируйте приведенный на рис. 4.5 алгоритм так, чтобы допу-
рЛ1ь. использ°вание операторов присваивания и конструкций IF—ELSE—
пи in пеРи°Да макрогенерацин. Можно считать, что вложенные конструк<
ции отсутствуют.
8. Дополните свой ответ к унр. 7 так, чтобы допустить наличие вло
^ииых предложений IF.
9. В чем фрагментами: а) LOOP наиболее LDT CLEAR • • существенная #8 X разница между следующими двумя
TIXR T
JLT LOOP
б) &CTR SET 0
WHILE a (&CTR LT 8)
&CTR • SET ENDW &CTR + I
10. Используя макроопределения на рис. 4.9а, получите текст макро
расширений для следующих предложений макроинициализации:
a) RDBUFF
. б) LABEL RDBUFF
в) RDBUFF
Fl, BUFFER, LENGTH,(04,12)
Fl, BUFFER, LENGTH,00
Fl,BUFFER,LENGTH
Какое значение будет иметь функция %NITEMS(&EOR) в последних двух
случаях?
11. Дополните свой ответ к упр. 7 так, чтобы включить предложение
WHILE. Можете не заботиться о вложенных конструкциях WHILE.
12. Дополните свой ответ к упр. 11 так, чтобы допустить вложенные
конструкции WHILE.
13. Переменные периода макрогенерации обычно рассматриваются к к
локальные для данного макроопределения. Таким образом, значение, при-
своенное переменной периода макрогенерации, может использоваться только
внутри того же самого макроопределения. В некоторых случаях, однако,
было бы удобно разрешить использование одной и той же переменной пе-
риода макрогенерации внутри двух связанных между собой макроопреде-
лений. Как это может быть реализовано?
14. Модифицируйте приведенный на рис. 4.5 алгоритм с тем,чтобы
включить в него обработку ключевых параметров макроопределении.
15. Некоторые макропроцессоры допускают использование предложении
макроинициализации, в которых одни параметры являются ключевыми,
другие — позиционными. Каким образом макропроцессор может обраоот
такого рода предложения макроинициализацип?
16. Каким образом можно было бы задать значения по умолчанию ‘
позиционных параметров? Какие изменения в алгоритме на рис. 4.о
шлось бы сделать для введения такой возможности?
17. Вспомним макроопределение RDBUFF на рис. 4.8а. Каждое
жеследующих предложений макроинициализацип этого макроопре it -
содержит ошибку. Какие из этих ошибок будут выявлены макропр. >-
ром, а какие — ассемблером?
a) RDBUFF F3,BUF,RECL,ZZ
(неправильное значение для &EOF)
б) RDBUFF F3,BUF,RECL, 04, 2048,01
(слишком много аргументов)
Упражнения
р) RDBUFF F3..RECL,04 ------
(ие определено значение „„
Г) RDBUFF F3.RECL BUF ЛЛЯ &bUFADR)
Неправильный иорпдок аргумс„гш)
Раздел 4.3
1. Предположим, что
изображенной на рис 4 5 п^Р роцессоР с логикой
нию- При обсуждении бЫЛ° выя*лёно°бч?оПезнВаТЬ РскУр‘ивную ма',алоги'»юП
л ARGTAB должны запоминат/г значения переменна Е^роге“ера-
EXPAND Какие другие значения так'го рекуРСив»ых вызовах X.PANl>1NG
ных способов реализации алгоритма? не°бходимо запоминать Рд“Цяелуры
2. Каким образом рекурсивный
на языке макропроцессора? макропроцессор может бить па
иино реализован
3. Можно ли в нерекурсивном макропроцессоре допустить появление
предложений макроинициалнзации внутри макроопределений? Каковы будут
преимущества и недостатки такого подхода?
4. Выберите два знакомых вам языка
уровня. Какие особенности этих языков будут
макропроцессора для них?
программирования высокого
существенны при реализации
5. Выберите какой-либо знакомый вам язык высокого уровня и язык
ассемблера. Какие особенности этих двух языков будут существенны для
реализации макропроцессора для них?
6. Опишите алгоритм взаимодействия макропроцессора, реализующего
режим «строка в строку», с ассемблером. 7
7. Перечислите вспомогательные функции и процедуры, которые могли
бы быть общими для ассемблера и встроенного макропроцессора.
Глава 5. Компиляторы
В этой главе мы обсудим структуру и функции компилято-
ров с языков программирования высокого уровня. Множество
Учебиых пособии целиком посвящено обсуждению компилято-
ров Мы не можем даже надеяться обсудить этот вопрос со
всей полнотой в одной главе. Вместо этого мы введем наиболее
важные концепции и понятия, связанные с компиляторами, а
также проиллюстрируем наше изложение рядом примеров. По-
сле обсуждения каждой темы мы дадим ссылки для тех чита-
телей, кто захочет более подробно разобраться в этой пробле-
матике.
В разд. 5.1 описаны основные функции простого однопросмо-
трового компилятора. Мы продемонстрируем работу такого ком-
пилятора путем прослеживания процесса трансляции простого
программного фрагмента от начала и до конца. Этот раздел
содержит более детальную информацию, чем другие разделы
этой главы, поскольку обсуждаемые понятия имеют фундамен-
тальное значение.
В разд. 5.2 обсуждаются машинно-зависимые расширения
базовой схемы, представленной в разд. 5.1. Эти расширения
относятся в основном к генерации объектного кода и оптими-
зации. В разд. 5.3 описаны некоторые машинно-независимые
дополнения к базовой схеме.
В разд. 5.4 описаны некоторые варианты построения компи-
ляторов. К ним относятся многопросмотровые компиляторы, ин-
терпретаторы, компиляторы на Р-КОД И компиляторы КОМИ:! -
торов. В заключение главы в разд. 5.5 приведены четыре пр
мера реальных компиляторов и систем построения компил.-,
ров, которые обсуждаются на базе концепций, введенных
предыдущих разделах.
5.1. Основные функции компилятора
В этом разделе обсуждаются операции, неооходнмь
компиляции программ типичного языка высокого уровня..,С1
честве примера мы будем использовать программу на ' ;1
изображенную на рис. 5.1, однако обсуждаемые кони П1Х
подходы приложимы к компиляции программ п с
языков.
5.1. Основные функции компилятопа
может
#за которой
. ), за которым следует вы
Для облегчения построения
уровня обычно описывается в терминах некоХоТ™ ВЬ,С0К0Г0
Эта грамматика определяет форму (синтаксис' ^шатики-
предложений языка. Например, оператор присваивашГ"”^
быть определен в грамматике как имя переменной
следует оператор присваивания (•='
ражение. Проблема компиляции можеГбы™ «Зва™
как проблема поиска соответствия написанных программистом
предложении структурам, определенным грамматикой и гене,
рации соответствующего кода для каждого предложения ».
1 PROGRAM STATS
2 VAR
3 SUM,SUMSQ,I,VALUE,MEAN,VARIANCE ; INTEGER
4 BEGIN
5 SUM := *0;
6 SUMSQ := 0;
7 FOR I := 1 TO 100 BQ
•S BEGIN
•9 READ i VALUE) ;
10 SUM := SUM + VALUE;
H SUMSQ SUMSQ + VALUE * VALUE
32 END;
13 MEAN s= SUM DIV 100;
14 VARIANCE SUMSQ DIV 100 - MEAN * MEAN;
15 WRI ТЕ(MEAN,VARIANCE)
36 END.
Рис. 5.1. Пример программы на Паскале.
удобнее представлять в
Предложения исходной программы
виде последовательности лексем (tokens), чем просто как стро-
ку символов. Лексемы можно понимать как фундаментальные
кирпичики, из которых строится язык. Например, лексемой мо-
жет быть ключевое слово, имя целой переменной, арифметиче-
ский оператор и т. д. Просмотр исходного текста, распознава-
ние и классификация различных лексем называются лексиче-
ским анализом. Часть компилятора,^ которая выполняс! эту
функцию, обычно называют сканером 2).
Как только лексемы выделены, каждое предложение пр
граммы может быть распознано как некоторая КОН^Р) '
языка, как, например, декларативные операторы или о р .
присваивания, описанные с помощью грамма! ики р ’^0.
зываемый синтаксическим анализом или синтакслл быцн0
ром, осуществляется той частью компилятора, Последним
называется синтаксическим анализатором генепация
шагом базовой схемы процесса трансляции
’> Автор придерживается термина «ко_
широко используемый у вас термин <тРанс «лексический анализатор».
2) В нашей литературе принят терм
///лмь ред.
^?ш‘:1шые%одыеДНаЗНаЧеННУ'0 последУю^й трансляции „
Хотя мы указали на три основных шага в процессе компм.
ляции лексический анализ, синтаксический анализ и генера-
цию кодов, важно отметить, что компилятор вовсе не обязан
делать три просмотра транслируемой программы. Для некото-
рых языков возможна компиляция программы за один про-
смотр. В этом разделе мы обсудим, как может работать одно-
просмотровыи компилятор. Однако компиляторы для других
языков и компиляторы, осуществляющие изощренную оптимиза
цию объектного кода или какой-либо другой анализ програм-
мы, обычно являются многопросмотровыми. Мы обсудим разбие-
ние процесса компиляции на отдельные просмотры в разд. 5 4
В разд. 5.5 приводится несколько примеров построения реаль-
ных компиляторов.
В последующих разделах мы обсудим основные элементы
процесса компиляции и проиллюстрируем их на примере про-
граммы, представленной на рис. 5.1. В разд. 5.1.1 вводятся ос-
новные понятия и обозначения, используемые для описания
грамматик языков программирования. В разд. 5.1.2—5.1.4 об-
суждаются функции лексического анализа, синтаксического ана-
лиза и генерации кодов.
5.1.1. Грамматики 11
Грамматика языка программирования является формальным
описанием его синтаксиса или формы, в которой записаны <и-
дельные предложения программы или вся программа. I рам >•
тика не описывает семантику или значения различных прсд.ю
жений. Информация о семантике содержится в программах .
нерации объектного кода. В качестве иллюстрации ‘
между синтаксисом и семантикой рассмотрим два предложи
1:=Л-К
и
где X и У являются действительными переменными, а - •;
К —целыми переменными. Эти два предложенияi имH1i>i,
паковый синтаксис. Оба являются операторами 1 1 ‘ е1111См,
в которых присваиваемое значение определяется в ‘ 0,1(1м
состоящим из двух имен переменных, разделенных шец-
сложения. Однако семантика этих двух предложенш с-
h В некоторых работах под грамматикой понимаю! нопялк.
ияюннч синтаксис и семантику. — Прим. ред.
225
5.1. Основные функции компилятора
но различна. Первое предложение говорит о том
ные в выражении должны быть сложены е b’J пеРемен'
целых арифметических операций, а результат сложен и я
быть присвоен переменной I. Второе предложен.* зачает *ло‘
жение с плавающей точкой, результат которого должен быть
преобразован в целое число перед присваиванием Очевидно
эти два предложения будут скомпилированы в совершенно паз’
личные последовательности машинных команд, хотя их Хм
магическое описание одинаково. Различия между ними ппо’
генерации объектного кода.
явятся на этапе
1 2 (prog) (prog-name) • — PROGRAM {prog-name) VAR {dec-list) BEGIN (stmt-list) END.
3 (dec-list) . — (dec) | (dec-list) ; (dec)
4 (dec) ; = (id-list) : (type)
б (type) • = INTEGER
6 > (id-list) s id | (id-list) , Id
7 (stmt-lisi) (stmt) | (stmt-list) ; (stmt)
8 (stmt) • = (assign) | (read) | (write) | (for)
9 (assign) • a Id ;= (exp)
10 (exp) • — (term) | (exp) 4- (term) | (exp) - (term)
11 (term) • — (factor) | (term) ♦ (factor) | (term) DIV (factor)
12 < factor) • ss id | int j ( (exp) )
13 (read) ; =; READ ( (id-list) )
14 (write) * a WRITE ( (id-list) )
15 (for) • a FOR (index-exp) DO (body)
16 (index-exp) • = id := (exp) TO (exp) •
17 (body) • a (stmt) 1 BEGIN (stmt-list) END
Рис. 5.2. Упрощенная грамматика Паскаля.
Существует несколько различных форм записи грамматик,
среди которых мы рассмотрим форму Бекуса — Наура (БНФ).
БНФ не самое мощное из известных средств описания синтак-
сиса. Фактически она даже не является вполне адекватной для
описания некоторых реально существующих языков программи-
рования. Однако эта форма достаточно проста, широко исполь-
зуется и предоставляет достаточные для большинства при-
ложений средства. На рис. 5.2 изображена одна из возможных
грамматик БНФ для очень узкого подмножества языка Пас-
каль. Полное описание грамматики БНФ для Паскаля содер-
жится в книге Йенсен [1974]. В этом разделе нам осталось
обсудить эту грамматику и показать, как она связана с приме-
ром программы, изображенным на рис. 5.1.
Грамматика БНФ состоит из множества правил вывода,
каждое из которых определяет синтаксис некоторой констр)К
Нин языка программирования. Рассмотрим, например, правши
13 на рис. 5.2:
(read) READ ( (id - list) )
Это определение синтаксиса предложения ^‘'^^^ожпо
обозначенное в грамматике как (read). С
8 Зак. 792
читать как «является по определению». С левой стороны от
этого символа находится определяемая конструкция языка (в
нашем случае— (read)), а с правой — описание синтаксиса этой
конструкции. Строки символов, заключенные в угловые скобки
( и ), называются нетерминальными символами (т. е. являются
именами конструкций, определенными внутри грамматики). То,
что не заключено в угловые скобки, называется терминальными
символами грамматики (лексемами). В этом правиле вывода
нетерминальными символами являются (read) и (id—list). Тер-
минальными символами являются лексемы READ, (,). Таким
образом, это правило определяет, что конструкция (read)
состоит из лексемы READ, за которой следует лексема (, за
ней следует конструкция языка, называемая (id—list), за ко-
торой следует лексема ). Пробелы при описании грамматических
правил не существенны и вставляются только для наглядности.
Для распознавания нетерминального символа (read) необ-
ходимо чтобы было определение для нетерминального символа
(id—list). Это определение дается правилом 6 иа рис. 5.2:
(id —list) ::= id | (id — list) , id
Это правило предлагает две возможности, разделенные симво-
лом |, для синтаксиса нетерминального символа (id—list).
Первая возможность состоит в том, что (id—list) состоит
просто из лексемы id (запись id означает идентификатор, рас-
познаваемый сканером). Другой вариант состоит в том, что
(id—list) состоит из (id—list), за которым следует лексема
«,», за которой следует лексема id. Обратите внимание, что это
правило является рекурсивным. Это означает, что конструкция
(id—list) определяется фактически в терминах себя самой.
Рассмотрев несколько примеров, вы убедитесь, что в соответ-
ствии с этим правилом, нетерминальным символом (id—list)
является любая последовательность из одной или более лексем
id, разделенных запятыми. Таким образом,
ALPHA
является нетерминальным символом (id—list), состоящим из
единственного идентификатора ALPHA;
ALPHA , BETA
также являются конструкцией (id—list), состоящей из конст-
рукции (id—list) ALPHA, за которой следует «,», за которой
идет идентификатор ВЕТА и т. д.
Результат анализа исходного предложения в терминах грам-
матических конструкций удобно представлять в виде дерева.
Такие деревья обычно называют деревьями грамматического
{VARIANCE}
(assign)
6
Рис. 5.3. Дерево грамматического разбора для двух предложений програм-
мы на рис. 5.1.
разбора или синтаксическими деревьями. На рис. 5.3а изобра-
жено дерево грамматического разбора для предложения
READ (VALUE)
с использованием только что обсужденных двух правил вы-
^Правило вывода 9 на рис. 5.2 дает определение синтаксиса
Предложения присваивания:
(assign) ;;= id := (exp)
PROGRAM (pfog-name) VAR (dec-list)
BEGIN (stat-list)
i—2L_
(stat-list)
id
{STATS}
(dec)
(type)
(id-list)
(stmt-list)
(stmt-list) i (stmt)
(stmt)
(write)
(id-list)
I {VARIANCE}
INTEGER
( (id-list) )
WRITE
(id-list)
{VALUE}
id
{MEAN}
(stmt) (assign)
(assign)
(exp)
{VARIANCE}
(id-list)
(id-list)
(stmt-list)
(stmt-list)
(stmt)
id
{VARIANCE}
id
{MEAN}
(exp)
(exp)
(tenn)
id
{MEAN}
(id-list)
{SUMSQ}
id
(I)
(stmt)
(id-list)
(assign)
{SUMSQ}
(exp)
id
{SUM}
(assign)
{SUM}
(exp)
(term)
(term) * (factor)
(term)
(term)
{MEAN}
int (factor)
{100} I
Lnt
{100} {MEAN}
(term)
(factor)
(term)
(factor)
id
{SUM}
id
{SUMSQ}
(factor)
Int
{0}
int
{0}
(for)
FOR
{index-exp)
DO
{X}
{exp}
TO
(exp)
{term}
(term)
(factor)
{body)
(stmt)
BEGIN
(stmt-list)
END
(factor)
Int
{100}
(stmt-list)
(stmt)
{stmt-list}
{stmt}
(read)
READ ( {id-list} )
(assign)
id
{SUM}
(exp}
(term)
(exp)
(assign)
(exp)
(tern}
(term)
*
Id
{$UMsq}
(exp'
(term)
(term)
(factor).
id
{VALUE}
(factor)
{factor}
(factor}
Id
{VALUE}
(factor)
Id
{VALUE)
Id
(SL’MSQ}
id
{VALUE}
Рис, 5.4, Дерево грамматического
id
{SUM}
разбора
для программы на
рис. 5.1.
-
Это означает, что конструкция <assign> состоит из лексемы id
за которой следует лексема :=, за которой идет конструкция
А ехр). Правило 10 дает определение конструкции (ехр):
<ехр) ::= (term) | (ехр) + (term) | (exp) — (term)
Используя те же соображения, что и при анализе конструкции
(id—list), мы видим, что это правило определяет конструкцию
(ехр) как состоящую из любой последовательности конструкций
(term), соединенных операторами плюс или минус. Анало-
гично правило 11 определяет конструкцию (term) как последо-
вательность конструкции (factor), разделенных, знаками * или
D1V. В соответствии с правилом 12 конструкция (factor) мо-
жет состоять из идентификатора id или целого int, которое
также распознается сканером, или из конструкции (ехр), за-
ключенной в круглые скобки.
На рис. 5.36 изображено дерево грамматического разбора
для предложения 14 на рис. 5.1, основанное на только что рас-
смотренных правилах вывода. Вы должны внимательно изучить
этот рисунок, чтобы убедиться в правильном понимании того,
как выполняется грамматический анализ исходного предложе-
ния на основании введенных грамматических правил.
В разд. 5.1.3 мы обсудим методы осуществления подобного син-
таксического анализа компиляторами.
Обратите внимание, что в соответствии с деревом граммати-
ческого разбора на рис. 5.36 умножение и деление производятся
перед сложением или вычитанием. Прежде всего должны вы-
числяться термы SUMSQ DIV 100 и MEAN * MEAN, по-
скольку эти промежуточные результаты являются операндами
(левым и правым поддеревом) операции вычитания. Иначе то
же самое можно выразить, сказав, что операции умножения и
деления имеют более высокий ранг (precedence), чем опсрап. ;
сложения и вычитания. Такое ранжирование операций явля* и
следствием того, как записаны правила 10—12 (см. упр. л )•
В разд. 5.1.3 мы увидим, как подобное ранжирование
быть использовано при осуществлении процесса грамматики
го разбора.
Дерево грамматического разбора па рис. 5.3 предста'... •
собой единственно возможный результат анализа э>и-. -
предложений в терминах грамматики, изображенной па !
Для некоторых грамматик подобной единственности м0А
существовать. Если для одного и того же предложения м
построить несколько различных деревьев грамматического |
бора, то соответствующая грамматика называется нсо( н '
ной (ambiguous). При разработке компиляторов 00Ь1Ч1Ю '11Ку
почитают пользоваться однозначными грамматиками. "ос с0.
в некоторых случаях неоднозначная грамматика остав‘,в
мнения относительно того, какой объектный код дол же
сгенерироаа,. для анализируемого предложения (ем., Ва„р„мер.
для всей программы рис^бЛ В^должны*матичсского разбора
лизировать этот рисунок, с тем чтобы понят?ателы,° пР°ана-
форма записи и структура программы соответствию?ппаТ3™
вывода грамматики, приведенной на рис. 5.2. У пРавилам
5.1.2. Лексический анализ
Лексический анализ включает в себя сканирование компи-
лируемом программы и распознавание лексем,1 составляютх
предложения исходного текста. Сканеры обычно строятся таким
образом, чтобы они могли распознавать ключевые слова one
раторы и идентификаторы так же, как целые числа числа с
плавающей точкой, строки символов и другие аналогичные кон-
струкции, встречающиеся в исходной программе. Точный пере-
чень лексем, которые необходимо распознавать, зависит, разу-
меется, от языки прогрзммировэния, ни который рассчитан
компилятор, и от грамматики, используемой для описания это*
го языка. Такие объекты, как идентификаторы и целые числа,
обычно распознаются сканером как отдельные лексемы. Од-
нако возможен и другой подход, в рамках которого эти лексе-
мы описываются правилами грамматики. Например, идентифи-
катор может быть определен следующим набором правил:
(ident) (letter) | (ident) (letter) | (ident) (digit)
(letter) ::=A | В | C | D | ... | Z
(digit) ::= 0 | 1 | 2 | 3 | ... | 9
В этом случае сканер будет распознавать в качестве отдельных
лексем единичные символы А, В, 0, 1 и т. д. Далее в процессе
грамматического разбора последовательность этих символов
будет интерпретирована как конструкция языка (ident). Однако
в рамках такого подхода распознавание простых идентифика-
торов должны осуществлять общие алгоритмы грамматического
разбора (например, описанные в следующем разделе). Специа-
лизированные программы сканера могут выполнить эту Ф>
цию гораздо более эффективно. Поскольку основная чаic ’
граммы состоит из подобных многосимвольных: | е<
Ров, сокращение времени компиляции может бы ? • альная
ственным. Кроме того, такие ограничения, как макси«альная
Длина идентификатора, гораздо легче учесть
общих алгоритмах грамматического разбора. ственно как
Аналогично сканер обычно распознает «^осредстве^^^^
односимвольные, так и многосимвольны . сматривать как
«троку символов READ предпочтительнее расе. 1
отдельную лексему, нежели чем последовательность, состоящую
из четырех лексем R, Е, A, D. Строка := будет распознана
как оператор присваивания, а не как символ :, за которым
Возможен, конечно, и такой подход, когда много-
лексемы рассматриваются как состоящие из от-
дельных лексехМ —
следует =.
символьные
.Лексема Ход
PROGRAM 1
VAR 2
BEGIN 3
END 4
END 5
INTEGER в
FOR 7
READ 8
WRITE 9
TO 10
DO 11
• • 12
• 13
» 14
15
+ 16
17
• 18
DIV 19
( 20
) 21
la 22
int 23
Рис. 5.5. Коды лек-
сем для грамматики
на рис. 5.2.
символов, но это сущест-
венно усложняет процесс грамматического
разбора.
Результатом работы сканера является
последовательность лексем. Для повыше-
ния эффективности последующих действий
каждая лексема обычно представляется
некоторым кодом фиксированной длины
(например, целым числом), а не в виде
строки символов переменной длины. При
подобной записи для грамматики, приве-
денной на рис. 5.2, лексеме PROGRAM
соответствует целое число 1, идентифика-
тору id соответствует число 22 и т. д.
Если распознанная лексема является
ключевым словом или оператором, такая
схема кодирования дает всю необходимую
информацию. В случае же идентификато-
ра дополнительно необходимо конкретное
имя распознанного идентификатора. То же
относится к целым числам, числам с пла-
вающей точкой, строкам символов и т. д.
Этого можно добиться за счет хранения
не только кода лексемы соответствующего
типа, но и дополнительного специфика-
тора лексемы. Спецификатор должен со-
держать имя идентификатора, значение
целого числа и т. д.— всю информацию,
распознанную сканером. Некоторые сканеры устроены
ким образом, что записывают идентификатор, когда (|
встретился впервые, в таблицу символов, аналог h'iioh
таблице символов, используемой в ассемблере. В этом ul-
спецификатором лексем-идентификаторов может служить )
затель на соответствующий элемент таблицы символов, иго -
зволяет избежать дополнительного поиска по таблицам на
следующих этапах компиляции. „0.
На рис. 5.6 изображен результат обработки сканере. ’
граммы, приведенной на рис. 5.1, с использованием код1 [
лексем, представленной на рис. 5.5. Для лексем типа 2- я10ТСя
тифпкаторы) соответствующими спецификаторами
указатели на таблицу символов (обозначаемые -
~SUMSQ и т. д.). Для лексем, имеющих тип 23 (целые
_ 51- Основные функции компилятора
Строка Тил лексемы Спецификатор лексемы г Строка Тип лексемы -соо Спецификатор лексемы
» । 10 22 ~ -«<
22 "STATS 'SUM
15
2 2
3 22 "SUM 22 "SUM
16
14
22 "SUMSQ 22 12 "VALUE
14 22 "I 11 22 15 "SUMSQ
•14
22 "VALUE 22 16 "SUMSQ
14
22 "MEAN 22 18 "VALUE
14
22 "VALUE
22 "VARIANCE 12 4
13 13 22 "MEAN
о 15
4 3 22 "SUM
5 22 "SUM 19
15 23 #100
23 #0 12
12 14 22 "VARIANCE
6 22 "SUMSQ 15
15 22 "SUMSQ
23 #0 19
12 23 #100
7 7 17
22 "I 22 "MEAN
15 18
23 #1 22 "MEAN
10 12
23 #100 15 9
11 20
8 3 22 "MEAN
S 8 14
20 22 "VARIANCE
22 "VALUE 21
21 16 5
12
Рис. 5.6. Результат лексического разбора програ ммы на рис.
спецификаторами являются значения соответствующих чисел
(обозначаемые 4М00 и т. д.).
- -------— ПТ1ГГП ПХ1 ИГ к' Я
' 'Мы” 11зобразшГи ^результат' работы^обрХ
кодов лексем; однако это вовсе не ознД ‘ каких-либо других
тывает целиком всю программу до < • . вь13ываемой в
действий. Чаще сканер является процедурой,
процессе грамматического разбора для получения очередной
лексемы. В этом случае результатом каждого вызова сканера
будет код очередной лексемы исходной программы (и если
необходимо, ее спецификатор). При этом задача сохранения
всей информации о лексемах, которая может понадобиться впо-
следствии, ложится на процесс грамматического разбора По-
добный пример работы сканера приведен в следующем раз-
деле.
В дополнение к своей основной функции — распознаванию
лексем — сканер обычно также выполняет чтение строк исход-
ной программы и, возможно, печать листинга исходной про-
граммы. Комментарии игнорируются сканером, за исключением
того случая, когда они должны быть напечатаны и, таким об-
разом, эффективно удаляются из исходной программы до на-
чала процесса грамматического разбора.
Процесс лексического разбора в том виде, как мы его опи-
сали, является весьма простым. Однако многие языки имеют
специфические особенности, которые должны учитываться при
программировании сканера. Например, сканер должен учиты-
вать информацию, связанную с соглашениями по формату рас-
положения строк исходной программы. Так, в языке Фортран
число в колонках 1—5 в исходном предложении должно рас-
сматриваться как номер предложения, а не как целое число.
Сканер должен учитывать также следующую языково-зависи-
мую информацию: являются ли пробелы ограничителями лексем
(как в Паскале) или нет (как в Фортране), могут ли предло-
жения свободно размещаться в нескольких строках входного
текста (как в Паскале) или же для этого требуются специаль-
ные признаки продолжения (как в Фортране).
Правила распознавания лексем могут различаться в разных
частях программы. Так, например, фрагмент READ не должен
распознаваться в качестве ключевого слова, если он встречает-
ся внутри строки символов, заключенной в кавычки. Пробелы
же оказываются существенными именно внутри таких закавы-
ченных строк, даже если они не существенны в остальных ча-
стях программы. Аналогично в программе на Фортране строка
F6.3 должна интерпретироваться по-разному в зависимости от
того, расположена ли она в предложении FORMAT или в ка-
ком-то другом месте программы.
В некоторых языках встречаются также нетипичные случаи,
которые должны учитываться сканером. Например, в предло-
жении на языке Фортран
DO 10 1=1, 100
сканер должен распознавать DO как ключевое слово, 10 как
номер предложения, I как идентификатор и т. д. Однако в
предложении
DO 10 1 = 1
сканер должен распознать DO 10 I как
предложение как предложение присваивая .*ИКатоР> а все
DO10I значения 1. В этом случае сЕ"’’""
вперед, есть ли запятая, прежде чем он сможет сделать
О правильной интерпретации фрагмента предложения DO с “4
ки, в которых зарезервированные слова могут употреблять™
» другом смысле, представляют для сканера еще'больше"тХ”
ностеи. В ПЛ/1, например, любое ключевое слово также ™
жет использоваться в качестве идентификатора. Такие слова',
как IF, THEN, ELSE, могут являться как ключевыми словами’
Так и именами переменных, определенных программистом Так
например, предложение
IF THEN = ELSE THEN IF = THEN; ELSE THEN = I?
является формально правильным, хотя и весьма экзотическим
предложением ПЛ/1. В этом случае сканер должен как-то
взаимодействовать с процессом грамматического разбора, что-
бы правильно интерпретировать каждое слово, или же он мо-
жет считать, что идентификаторы и ключевые слова являются
элементами одного и того же класса лексем, оставляя задачу
их различения процессу грамматического разбора.
В настоящее время разработан ряд средств для автомати-
ческого конструирования лексических анализаторов по спе-
цификациям, записанным на специальном языке. Описание од-
ного из таких средств, обладающих возможностями обработки
рассмотренных выше нестандартных ситуаций, содержится в
работе Ахо [1977].
5.1.3. Синтаксический анализ
Во время синтаксического анализа предложения исходной
программы распознаются как языковые конструкции, описывае
мые используемой грамматикой. Мы можем рассматривать эг т
процесс как построение дерева грамматического раз юра’
транслируемых предложений. Методы грамматическог х0.
Можно разбить на два больших класса восхос, ( _ Гоам-
дящие — в соответствии с порядком построения iсверху
^этического разбора. Нисходящие методьL конеч-
вниз) начинают с правила грамматики, опр , ' q разбора, и
нУю цель анализа с корня дерева грамме рлы дерева
'’ьггаются так его наращивать, чтобы пос^^- !‘ложения. Вос-
с°ответствовали синтаксису анализируем от с конечных
ходящие методы (методы снизу вверх; ь аются объединить
Узлов дерева грамматического разбора i
их построением узлов все более и более высокого уровня до
тех пор, пока не будет достигнут корень дерева.
Разработано множество методов грамматического разбора
большинство из которых применимо лишь к грамматикам'
удовлетворяющим определенным требованиям. В этом раз те те
мы кратко опишем один нисходящий и один восходящий ме-
тод, а также продемонстрируем применение этих методов к на-
шему примеру программы. Мы не собираемся описывать все
детали обоих методов. Вместо этого мы попытаемся продемон-
стрировать общин подход и снабдить ссылками читателей, же-
лающих изучить эти методы более подробно.
Восходящий метод грамматического разбора, который мы
рассмотрим, называется методом операторного предшествова-
ния. Он основан па анализе пар последовательно расположен-
ных операторов исходной программы и решении вопроса о том,
какой из них должен выполняться первым. Рассмотрим, напри-
мер, арифметическое выражение
A -f- В * С — D
В соответствии с обычными правилами арифметики умножение
и деление осуществляются до сложения и вычитания. Можно
сказать, что умножение и деление имеют более высокий уро-
вень предшествования, чем сложение и вычитание. При анализе
первых двух операторов (+ и *) выяснится, что оператор ф
имеет более низкий уровень предшествования, чем оператор *.
Часто это записывают следующим образом:
Аналогично для следующей пары операторов (* и —) опера-
тор * имеет более высокий уровень предшествования, чем опе-
ратор —. Мы можем записать это в виде
* • >• —
Метод операторного предшествования использует подобные
отношения между операторами для управления процессом
грамматического разбора. В частности, для рассмотренною
арифметического выражения мы получили следующие отноше-
ния предшествования:
А-фВ*С —D
Отсюда следует, что подвыражение В-»С должно быть вьш
лено до обработки любых других операторов рассматриваемою
выражения. В терминах дерева грамматического разбора ою
означает, что операция * расположена на более низком уровне
узлов дерева, чем операции ф или —. Таким образом, рассм-11
ривасмый метод грамматического оачбппд п-
конструкцию В * С, интерпретируя ее в теп^ш! распозиать
грамматики, до анализа соседних тепмпп ™рминах заданной
Предшествующее изложение иллюстрирует oXbhv"'
на которой основан метод грамматического разбоп. У‘° ИДСЮ’
НЫЙ на отношениях операторного предшествования R°CTP°CH'
этого метода анализируемое предложении ™ В рамках
направо до тех пор, пока не бу пет цай1Р„е ска111|рУется слева
раторы которого имеют более^ высокий ° водвыражение, опе-
ния, чем соседние операторы. Далее это’ Пт"Ь предшествова-
знается в терминах правил вывода игпг подвыражение распо-
Этот процесс продолжается до тех пор покГграмматики-
нут корень дерева, что и будет означать л™ будет достиг’
грамматического разбора. ДУалее °мы рассмот нм"
описанного подхода к нашему примеру программы
Первым шагом при разработке процессора грамматического
разбора основанного на методе операторного предшествования
должно быть установление отношении предшествования между
операторами грамматики. При этом под оператором понимается
любой терминальный символ (т. е. любая лексема). Таким об-
разом, мы должны, в частности, установить отношение предше-
ствования между лексемами BEGIN, READ, id и (. Матрица
на рис. 5.7 задает отношения предшествования для грамматики
приведенной на рис. 5.2. Каждая клетка этой матрицы опреде-
ляет отношение предшествования (если оно существует) между
лексемами, соответствующими строке и столбцу, па пересечении
которых находится эта клетка. Например, мы видим, что
PROGRAM = VAR
и
BEGIN <• FOR
Отношение = означает, что обе лексемы "«Хч^оаммати-
уровень предшествования и должны рассматрпв | щструк-
ческим процессором в качестве составляющих о, к цредше-
ции языка. Обратите внимание, что для от н1Ь1е для
ствования не выполняются некоторые правил , [
отношения арифметического порядка. Например,
; • > END
но
’ END ; ексем
Обратите внимание также на то, , что> ж™ означает, что
отношение предшествования не сущ } .^ходиться рядом ни
соответствующие пары лексем нс м У ‘жсни11. Если подоб-
в каком грамматически правильном I оетятся в процесс
ная комбинация лексем все же L
грамматического разбора, то она должна рассматриваться как
синтаксическая ошибка.
Существуют алгоритмы автоматического построения матриц
предшествования, подобных изображенной на рис. 5.7, на осно-
ве описания грамматики (см., например, Ахо [1977]). Для при-
менимости метода операторного предшествования необходимо,
PROGRAM
VAR
BEGIN
END
INTEGER
FOR
READ
WRITE
TO
DO
t
»
• c=
4-
♦
DIV
(
)
id
ini
Рис. 5.7. Матрица предшествования для грамматики на рис. 5.2.
Напоимеп п предшествования были заданы однозначно.;
и Л RFCтм°Л?Н0 6ЫТЬ °ДновРеменно отношений ; < BEGIN
ки пнг с; о г?то требование выполняется для граммати-
измририиа ’ однако надо иметь в виду, что несущественные се
пеоестяпит >°ГУТ пРивести к тому, что некоторые из отношений
Р У ыть однозначными и метод оперативного предше-
ствования станет неприменимым.
На рис. 5.8 изображен результат применения метода опера-
торного предшествования к двум предложениям программы
рис. 5.1. На рис. 5.8а изображен анализ предложения REA|?
строки '9 этой программы. Это предложение анализируется ш’
г
5.1. Основные функции компилятора
239'
лексемам слева направо. Для каждой пары соседних опеоатоп™
определено отношение предшествования. В строке <\Р
рис. 5.8а процессор грамматического разбора выделил boar3
мент, ограниченный отношениями <• и ->, для распознавания
в терминах грамматики. В данном случае этот фрагмент еп
держит единственную лексему id. Эта лексема может быть пас
познана как нетерминальный символ (factor) в соответствии с
грамматическим правилом 12. Однако эта лексема может был
также распознана как нетерминальные символы (prog__name)
(правило 2) и (id — list) (правило 6). Для рассматриваемого
метода не важно, какой конкретно нетерминальный символ рас-
познан. Лексема id интерпретируется просто как некоторый
нетерминальный символ (Ni>. В строке (п) иа рис. 5.8а изо-
бражен результат анализа предложения, в котором лексема id
заменена на (Nj>. Из него следует, что далее надо распозна-
вать правый фрагмент предложения.
Строка (ii) на рис. 5.8а также изображает отношение пред-
шествования для новой версии анализируемого предложения.
Процессор грамматического разбора, основанный на отношении'
предшествования, обычно использует стек для хранения полу-
ченных от сканера (но еще грамматически не распознанных)
лексем для их последующего распознавания. Отношения пред-
шествования определены лишь для терминальных символов.
Таким образом, нетерминальный символ (N]> не будет вовле-
чен в этот процесс, и далее отношения предшествования будут
установлены между терминальными символами ( и ). В данном
случае для последующего распознавания будет выделен фраг-
мент
READ ( <М,> )
который соответствует, за исключением имени нетерминального
символа, грамматическому правилу 13. Это правило является
единственным, применимым для этого фрагмента. Однако, так
же как и прежде, мы просто обозначим этот фрагмент как не-
терминальный символ (N2>-
На этом разбор предложения READ закончен. Если мы
сравним дерево грамматического разбора на рис. 5.3а с только
что построенным, то увидим, что они полностью совпадают, за
исключением используемых имен нетерминальных символов. * го
означает, что мы правильно определили синтаксис анализируе-
мого предложения, что и является целью процесса граммати ш
ского разбора. Сами же имена нетерминальных символов ыли
выбраны произвольно автором записи грамматики и исимск
никакого отношения к смыслу предложений исходной
граммы. и пплиргг
На рис. 5.86 изображен аналогичный nolliaroiBi^11n ,тпоке
грамматического разбора предложения присваивая!
Гл. 5. Компиляторы
0) • .. BEGIN READ
<
( id. )
* < >
00 ... BEGIN • READ ( XNJ ) J
(Nj)
(»0 ... BEGIN (Ng)
id
{VALUE}
<n2>
a
f) ... id! !« ld2 DIV
< 0. < >
(li) ... ldL !• OM DIV int —
< < < >
(HO ... DIV (n2) -
< dk < >
(iv) •«» Id। (N3> id3 *
< < < >
•
id
(VALUE)
OM
I
id?
(SUMSQ1
(N2)
I I
ld2 int
(SUMSQ| (XCOJ
<N3>
I I
<N]_) (N2)
I I
ld2 DIV int
{SUMSQ} {100}
w
... iax :«« (n3> - (N4) * id4 :
< * < < < >
(N3)
гН
(Nx> <N2> W
id'. D V 1»* la5,
{SUMSQ} (100| {MEAN}
<N3>
(vl) ... Idj f« (N3> ~ (tf4) • (n5)
** * «5. <4. >>
<Nj> <N2>
I I
ld2 DIV bi*
{SUMSQ} {100}
(N4> <n5>
{MEAN} (MEAN}
(VIQ ... ИЦ
<n7>
(viii) ... i<h
< ==
Рис. 5.8. Грамматический разбор двух предложений программы по рис. 5.1
Методом операторного предшествования.
14 программы на рис. 5.1. Обратите внимание, что процесс ска-
нирования слева направо продолжается на каждом шаге грам-
матического разбора лишь до тех пор, пока не определился
очередной фрагмент предложения для грамматического ра< по-
знавания, т. е. первый фрагмент, ограниченный отношениям!
5* и *>. Как только подобный фрагмент выделен, он ш с
нретируется как некоторый очередной нетерминалы этот
8 соответствии с каким-нибудь правилом граммат
процесс продолжается до тех пор, пока предложение не будет
распознано целиком. Вы должны внимательно проследить все
этапы, изображенные на рис. 5.86, для того, чтобы убедиться в
правильном понимании процесса анализа с использованием
матрицы предшествования, приведенной на рис. 5.7. Обратите
внимание, что каждый фрагмент дерева грамматического1 раз-
бора строится, начиная с оконечных узлов вверх, в сторону
корня дерева. Отсюда и возник термин восходящий разбор
Сравнивая деревья грамматического разбора, изображенные
на рис. 5.86 и рис. 5.36, мы обнаружим некоторые различия
Например, идентификатор SUMSQ на рис. 5.3 был сначала
интерпретирован как <factor>, а потом как <term>, являющийся
одним из операндов операции DIV. На рис. 5.86 идентификатор
SUMSQ интерпретирован как единственный нетерминальный
символ <Ni>, являющийся операндом DIV. Таким образом,
<Ni> на дереве, изображенном на рис. 5.86, соответствует двум
нетерминальным символам — (factor) и <term> — на рис. 5.36.
Имеются и другие подобные различия между этими двумя де-
ревьями.
Они вытекают из свободы образования имен нетерминаль-
ных символов, распознаваемых в рамках метода операторного
предшествования. Интерпретация SUMSQ на рис. 5.36 сначала
в качестве <factor>, а потом <term> является просто переимено-
ванием нетерминальных символов. Такое переименование необ-
ходимо, поскольку в соответствии с грамматическим правилом
11 первым операндом операции умножения должен быть (term),
а не (factor). Так как для метода операторного предшествова-
ния имена нетерминальных символов несущественны, то подоб-
ное переименование в процессе распознавания становится не-
нужным. Собственно говоря, три различных имени (ехр),
(term) и (factor) — были включены в грамматику только как
средства описания отношения предшествования между опер.ло-
рами (например, для указания того, что умножение сл ..ai
выполнять прежде сложения). Поскольку эта информання
держится в нашей матрице предшествования, то становится и*,
нужным различать эти три имени в процессе грамматичеион о
разбора. с.
Хотя мы проиллюстрировали метод операторного
ствования только на разборе отдельных предложении, эт"* ‘ е
тод применим и для всей программы в целом. Вы, jy нс.
попробовать применить этот метод к программе на рис.
пользуя матрицу предшествования на рис. 5.7. Результа
жен совпадать с деревом грамматического разбора, изо
ном на рис. 5.4, за исключением различий в именах нс <
нальных символов, подобных только что рассмотренным. .
Другой метод грамматического разбора, который 14 ‘
смотрим в этом разделе, это нисходящий метод, назь »
рекурсивным спуском. Процессор грамматического разбора, ос-
нованный на этом методе, состоит из отдельных процедур’для
каждого нетерминального символа, определенного в граммати-
ке. Каждая такая процедура старается во входном потоке най-
ти подстроку, начинающуюся с текущей лексемы, которая мо-
жет быть интерпретирована как нетерминальный символ, свя-
занный с данной процедурой. В процессе своей работы она
может вызывать другие подобные процедуры или даже рекур-
сивно саму себя для поиска других нетерминальных символов
Если эта процедура находит соответствующий нетерминальный
символ, то она заканчивает свою работу, передает в вызвавшую
ее программу признак успешного завершения и устанавливает
указатель текущей лексемы на первую лексему после распо-
знанной подстроки. Если же процедура не может найти под-
строку, которая могла бы быть интерпретирована как требуе-
мый нетерминальным символ, она заканчивается с признаком
неудачи или же вызывает процедуру выдачи диагностического
сообщения и процедуру восстановления.
Рассмотрим в качестве примера грамматическое правило 13
на рис. 5.2. Процедура метода рекурсивного спуска, соответ-
ствующая нетерминальному символу (read), прежде всего ис-
следует две последовательные лексемы, сравнивая их с READ
и (. В случае совпадения эта процедура вызывает другую про-
цедуру, соответствующую нетерминальному символу <id — list).
Если процедура <id — list) завершится успешно, то процедура
(read) сравнивает следующую лексему с ). Если все эти про-
верки окажутся успешными, то процедура (read) завершается с
признаком успеха и устанавливает указатель текущей лексемы
на лексему, следующую за ). В противном случае процедура
(read) завершается с признаком неудачи.
Эта процедура лишь немного сложнее, чем те несколько
определенных грамматикой альтернатив для соответствующих
нетерминалов. Дополнительно процедура должна решать, ка-
кую альтернативу попробовать в качестве следующей. Для ме-
тода рекурсивного спуска необходимо, чтобы соответствующую
альтернативу можно было выбрать на основании анализа оче-
редной входной лексемы. Существуют другие нисходящие ме-
тоды грамматического разбора, для которых это требование
может не выполняться. Однако они не являются столь эффек-
тивными, как метод рекурсивного спуска. Так, например, про-
цедура, соответствующая (stmt), анализирует очередную лексе-
му Для того, чтобы выбрать одну из четырех возможных аль-
тернатив. Если это лексема READ, то вызывается процедура,
соответствующая нетерминальному символу (read); если^ это
лексема id, то вызывается процедура, соответствующая m те. ।
минальному символу (assign), поскольку это единственная аль
^рнатива, которая может начинаться с лексемы id, и т. д.
Если мы попытаемся написать полный набор процедур
грамматики на рис. 5.2, мы столкнемся
ностыо. Процедура для <id —
для
ностыо. процедура для <id-list>, cootbotcw/S^bnW6
будет не в состоянии выбрать одну из ДвухУальтернатив м
скольку обе альтернативы id и <id — lists mofvt Рнат11в’ П0‘
лексемы id. Тут скрыта и более существенная трудноет^Ести
процедура каким-либо образом решит попробовать вТ0Х ал ‘
тернатнву «,<1 _ l,st>, id). т0 011а немедленно вь,зоветт »» аль-
но саму себя для поиска нетерминального символа (id_list).
1 2 (prog) (prog-name) PROGRAM (prog-name) VAR (dec-list) BEGIN (stmt-list) END.
(dec-list) • (dec) { ; (dec) }
4 (dec) (id-list) : (type)
5 (type) •»» INTEGER
ба (id?list> id { . Id }
7а <s tin t~l is t > • (stmt) { ; (stmt) }
8 (stmt) • ;«=» (assign) | (read) | (write) | (for)
9 (assign) ::=» id (exp)
Юа (exp) • (term) { -f* (term) ] - (term) }
Па (term) (factor) { * (factor) I DIV (factor) }
32 (factor) id | int | ( (exp) )
33 (read) • •» READ ( (id-list) )
34 (write) WRITE ( (id-list) )
15 (for) :;=з FOR (index-exp) DO (body)
36 (index-exp) ::= Ad (exp) TO (exp)
17 (body) • ;сз (stmt) J BEGIN (stmt-list) END
Рис. 5.9. Упрощенная грамматика Паскаля, модифицированная для грамма-
тического разбепя методом рекурсивного спуска.
Это приведет еще к одному рекурсивному вызову и т. д., в ре-
зультате чего образуется бесконечная цепочка рекурсивных вы-
зовов. Причина этого заключается в том, что одна из альтер-
натив для <id— list) начинается также с <id — list). Нисходя-
щий грамматический разбор не применим непосредственно для
грамматик, содержащих подобные левые рекурсии. Ге же.
проблемы возникнут и в отношении правил 3, 7, 10 и И. Ме-
тоды исключения левой рекурсии из правил грамматики можно
найти в работах Грис [1971] и Ахо [1977]. _ .
На рис. 5.9 изображена та же грамматика, что и на рис. о—
но с исключенной левой рекурсией. Рассмотрим, например, при-
вило 6а на рис. 5.9:
(id — list) := id { , id }
Эта нотация, являющаяся широко принятым расширением
означает, что конструкция, заключенная в фигурные ch'1
может быть либо опущена, либо повторяться один пли ю-
число раз. Таким образом, правило 6а определяет нетермпп<-
ный символ <id — list) как состоящий из единственной у
мы id или же из произвольного числа следующих друг 311 —т>
гом лексем id, разделенных запятой. Это очевидно, эквпва-
215
bl Основные функции ком пил я тора
но правилу 6 на рис. 5.2. В соответствии с этим новым опре-
делением процедура, соответствующая нетерминальному симво-
лу <id — list), сначала ищет лексему id, а затем продолжает
сканировать входной текст до тех пор, пока следующая пара
лексем не совпадет с запятой и id Такая запись устраняет
проблему левой рекурсии, а также решает вопрос, какую из
возможных альтернатив <id — list) пробовать первой.
Аналогичные изменения сделаны в правилах За, 7а, 10а и
11а на рис. 5.9. Вам надо сравнить эти правила с соответ-
ствующими им правилами на рис. 5.2 для того, чтобы убедить-
ся в понимании сделанных изменений. Обратите внимание, что
грамматика осталась рекурсивной: (ехр) определено в терминах
(term), который в свою очередь определен в терминах (lactor),
а одна из альтернатив для нетерминального символа factor)
включает в себя (ехр). Это означает, что рекурсивные вызовы
поонедур грамматического разбора по-прежнему возможны. Од-
нако непосредственная левая рекурсия устранена. Цепочка вы-
човов начиная с (ехр) и далее процедур, связанных с (term)
/factor) И опять (ехр), должна продвинуть указатель текущей
лексемь! из входного файла как минимум на одну лексему
вперед. _ _
На рис. 5.10 изображен грамматический разбор методом
рекурсивного спуска предложения READ в строке 9 на рис 5 1
с использованием грамматики на рис. 5.9. Па рис. 5.10а изо-
бражены процедуры, соответствующие нетерминальным сими >-
лам (read) и (id—list), логика которых совпадает с приведен-
ным выше описанием. При этом предполагается, что переменная
TOKEN содержит тип следующей лексемы из входного потока
(в рамках схемы кодирования, изображенной на рис. 5.5).
Вам надо внимательно ознакомиться с этими процедурами, что-
бы убедиться, что вы понимаете, каким образом они получены
из исходной грамматики.
Заметьте, что в процедуре IDLIST символ запятая (,), за
которым не следует лексема id, рассматривается как ошибка и
процедура заканчивается с признаком неудачи. Если же ш
дователыюсть лексем типа «id, id» является правильно1! ьо
струкцией языка, то метод рекурсивного спу-ска
пых результатов. Для такой гРаммат11К‘1 Da360na, которые
вать более сложные методы граммат ичс к’ ». возврат по
Должны допускать во время нисходящи 1 чт0 за послед-
входной строке после обнаружения того факта,
ней запятой не следует лексема id. ппоиесс грамматиче-
На рис. 5.106 графически пР“"%вХ"Рдля анализируемо.
СКОРО разбора метолом рекурсивного ’ вызов процедуры
го предложения. На фрагменте (.изображе 0
READ, которая Обнаружила лексемы КЬД Во фрагменте
Юке это изображено штриховыми лнн
procedure READ
begin
FOUND :« FALSE
i Г TOKEN = 8 CREAM then
begin
перейти к следующей лексеме
if TOKEN - 20 £ < I then
begin
перейти к следующей лексеме
if IDLIST закончилась успешно then
if TOKEN - 21 С ) J then
begin
FOUND s« TRUE
перейти и следующей лексеме
end Cif ) )
end Cif ( }
. end Cif READ)
if FOUND - TRUE then
успешное завершение
else
неудачное завершение
end CREAD3
procedure•IDLIST
begin
FOUND 8* FALSE
if TOKEN « 22 Cid) then
begin
FOUND S= TRUE
перейти к следующей лексеме
while (TOKEN =14 С,Э) and (FOUND * TRUE)
begin
перейти к следующей лексеме
if TOKEN = 22 (id) then
перейти к следующей лексеме
else
FOUND := FALSE
end {while!
end -Cif id!
if FOUND » TRUE then
успешное завершение
Else
неудачное завершение
end (IDLIST!
<D
‘REAO
Рис. 5.10. Грамматический разбор предложения
спуска.
READ методом рёкуренв»010
(ii) процедура READ вызвала процедуру IDI 1ЧТ г™, г
штриховой линией), которая обработала л"ксему
Менте (...) процедура IDLIST закончила свою работу, пер*^
управление процедуре READ с признаком успешного ST
„ня; процедура READ обработала входную лексему ) 3Лзершс'
анализ исходного предложения завершен. Процедуоа dfah
закончит свою работу с признаком успешного завеошения
ЧТо означает, что нетерминальный символ <read> обнаружен Or
ратите внимание, что последовательность вызова процедур й
обработки лексем целиком определяется структурой ппе™-й
пня READ. Фрагмент (iii) полностью совпадает с деревом ГоТм
магического разбора на рис. 5.3а. Обратите внимание также нй
то, что дерево грамматического разбора строилось, начиная со
своего корня, что и повлекло за собой термин нисходящий раз-
бор.
На рис. 5.11 представлен разбор методом рекурсивного спу-
ска оператора присваивания в строке 14 на рис. 5.1. На
рис. 5.11а изображены процедуры для нетерминальных симво-
лов, необходимые для разбора этого предложения. Вы должны
внимательно сравнить эти процедуры с соответствующими пра-
вилами грамматики. На рис. 5.116 изображены шаги граммати-
ческого разбора (вызовы процедур и обработка лексем), ана-
логичные приведенным на рис. 5.106. Читателю настоятельно
рекомендуется проследить каждый шаг анализа этого предло-
жения с использованием процедур рис. 5.11а. Сравните де-
ревья грамматического разбора на рис. 5.116 и рис. 5.36. Обра-
тите внимание, что различия между этими
точности соответствуют различиям между
браженными на рис. 5.9 и рис. 5.2.
двумя деревьями в
грамматиками, изо-
Мы привели примеры грамматического разбора отдельных
предложений методом рекурсивного спуска. Однако этот метод
применим и ко всей программе в целом. В этом случае для
осуществления синтаксического анализа следует просто обра-
титься к процедуре, соответствующей нетерминальному символу
В результате работы этой процедуры будет построено
Дерево грамматического разбора для всей программы. Вы може-
те написать недостающие процедуры для всех нетерминальных
символов грамматики на рис. 5.9 и применить метод рекурсив-
ного спуска к программе на рис. 5.1. В качестве результата
вы должны получить дерево грамматического разбора, анало
гичное изображенному на рис. 5.4. Различия должны быть св -
заны только с теми модификациями, которые имеются в гра
батике на рис. 5.9. n-revT-
Обратите внимание, что в языке программиров -
Ствуют какие бы то ни были особенности, заставля,*
Предпочтение одному из методов грамматическое Р< - ••
Использовали один восходящий и один нисход щ
procedure ASSIGN
begin
FOUND : = FALSE
If TOKEN -22 (id) then
begin
перейти к следующей лексеме»
if TOKEN =15 <:=) then
begin
перейти к следующей лексеме
if EXP завершилась успешно then
FOUND r TRUE
end (if :=!
end (if id!
if FOUND » TRUE then
успешное завершение
else
неудачное завершение
end (ASSIGN!
procedure EXP
begin
FOUND 2= FALSE
if TERH завершилась успешно then
begin
FOUND := TRUE
while ((TOKEN = 16 (t! или (TOREN x 17 (-)))
and (FOUND = TRUE) do
begin
перейти к следующей лексене
if TERM завершилась неудачно then
FOUND s = FALSE
end (while!
end (if TERM!
if FOUND = TRUE then
успешное завершение
else
неудачное завершение
end (EXP!
procedure TERM
begin
FOUND FALSE
if FACTOR завершилась успешно then
begin
FOUND :« TRUE
while ((TOKEN =18 M) или (TOKEN = 19 (DIM)))
and (FOUND = TRUE) do
begin
перейти и следующей лексеме
if FACTOR закончилась неудачно then*
FOUND : = FALSE
end (while!
end (if FACTOR!
if FOUND =TRUE then
Успешное завершение
else
неудачное завершение
and (TERM!
procedure FACTOR
begin
FOUND s= FALSE
if (TOKEN = 22 Cid)) или TOKEN =23 CinU) then
begin
FOUND := TRUE
перейти к следующей лексеме
end Cif id или int)
else
if TOKEN =20 C ( J then
begin
перейти к следующей лексеме
if EXP завершилась успешно then
if TOKEN = 21 C ) ) then
begin
FOUND s= TRUE
перейти к следующей лексеме
end Cif ) )
end Cif < )
if FOUND = TRUE then
успешное завершение
else
неудачное завершение
end CFACTORJ
(i) ASSIGN
Чг—IП
/ I
1<ц :**
{VARIANCE}
f
id;7
{SUMSQ}
ini
{100}
idn
{SUMSQ}
б
Рис. 5.11. Грамматический разбор предложения присваивания методом ре
курсивного спуска.
разбора одной и той wa
чески одинаковой грамматикиРПл^Ы С использован»ем практи-
использование этих метоп™ н Возможно также одновременное
ют метод рекурсивного rnv^TTOpbIe компиляторы использу-
относительно ВЫСОКОГО /ДЛЯ Распознавания конструкций
предложений языка) яУРпПТл <напРимер, до уровня отдельных
логичный методу onwaTo„^” пе₽еклю<<аЮтся на метод. а»а-
таких конструкций как и™Г° пРедшествования для анализа
Дальнейшее обсуждении ример’ аРифметические выражения,
содержится в работах дГрамматического разбора
Ц1971). работах Ахо [1977], Льюис [1976] н Грнс
J 5.14. Генерация кода
Г После того как синтаксис программы проанализирован по-
следним шагом процесса компиляции является генерация объ-
ектного кода. В этом разделе мы обсудим простой метод кото-
рый генерирует объектный код для каждого фрагмента про-
граммы, как только распознан синтаксис этого фрагмента
Для реализации рассматриваемого метода генерации объ-
ектного кода необходим набор подпрограмм, соответствующих
каждому правилу и каждой альтернативе в правилах грамма-
тики. Как только в результате процесса грамматического раз-
бора будет распознан фрагмент текста исходной программы,
соответствующий некоторому правилу грамматики, вызывается
подпрограмма, соответствующая этому правилу. Эти программы
часто называют семантическими программами, поскольку вы-
полняемые ими действия связаны со смыслом, который мы свя-
зываем с соответствующими конструкциями языка. В рамках
нашей простой схемы эти семантические программы непосред-
ственно генерируют объектный код. Поэтому мы будем назы-
вать их программами генерации кода. В более сложных компи-
ляторах подобные семантические программы могут генерировать
некоторую промежуточную форму представления программы,
пригодную для последующего анализа с целью генерации более
эффективного объектного кода. Мы рассмотрим эту возмож-
ность более детально в разд. 5.2 и 5.3.
Программы генерации кода, которые мы обсудим в этом
разделе, предназначены для использования с грамматикой на
рис. 5.2. Как мы уже видели, ни один из методов грамматиче-
ского разбора, обсуждавшихся в разд. 5.1.3, не распознает в
точности те конструкции, которые описаны грамматикой. Метод
операторного предшествования игнорирует некоторые нетерми-
нальные символы, а метод рекурсивного спуска вынужден ис-
пользовать несколько модифицированную грамматику. Сущест-
вуют, однако, методы грамматического разбора ненамного слож-
нее описанных, которые могут осуществлять грамматический
разбор в строгом соответствии с грамматикой на рис. 5.2. Мы
выбрали именно эту грамматику для обсуждения программ ге-
нерации кода только для того, чтобы подчеркнуть, что методы
генерации кода не связаны непосредственно с каким-либо кон-
кретным методом грамматического разбора.
Ж Генерируемый код, очевидно, зависит от того, на каком
компьютере будет выполняться компилируемая программа.
® этом разделе мы будем рассматривать генерацию объектного
кода для машины УУМ/ДС. Для своих рабочих данных наши
программы генерации кода будут использовать две стр)кт\р .
описок и стек. Данные, попадающие в список, выбираются в
том же порядке, в котором они туда записывались, т.
соответствии со стратегией «первым пришел — первым ушел».
Данные, попадающие в стек, выбираются из него в обратном
порядке, т. е. в соответствии со стратегией «первым пришел_•
последним ушел». Переменная LISTCOUNT используется в ка-
честве счетчика элементов, содержащихся в данный момент в
списке. Программы генерации кода также используют специфи-
каторы лексем, описанные в разд. 5.1.2 и обозначаемые S (лек-
сема). Для лексемы id выражение S(id) является именем со-
ответствующего идентификатора или указателем на него в таб-
лице символов. Для лексемы int выражение S(int) является зна-
чением соответствующего целого числа, например 100.
Большинство программ, названных нами программами гене-
рации объектного кода, в качестве результата своей работы
действительно генерируют фрагменты объектного кода для ком-
пилируемой программы. Мы символически запишем эти фраг-
менты, используя язык ассемблера для УУМ. Вы должны по-
мнить, однако, что в действительности генерируемый код чаще
всего записывается на языке машинных команд, а не на языке
ассемблера. Мы предполагаем, что после генерации каждого
фрагмента объектного кода указатель свободной памяти
LOCCTR модифицируется таким образом, чтобы он все время
указывал на первую свободную ячейку компилируемой програм-
мы (в точности так, как это происходит в ассемблере).
Рис. 5.12 иллюстрирует процесс генерации объектного кода
для предложения READ в строке 9 программы рис. 5.1. Для
удобства дерево грамматического разбора этого предложения
повторено на рис. 5.12а. Это дерево можно получить многими
различными методами грамматического разбора. Однако неза-
висимо от используемого метода на каждом шаге процесса
грамматического разбора распознается самая левая подстрока
входного текста, которая может быть интерпретирована в соот-
ветствии с каким-либо из правил грамматики. В методе опера-
торного предшествования подобное распознавание осуществля-
ется, когда подстрока входного текста редуцируется к некото-
рому нетерминальному символу <N(>. В методе рекурсивного
спуска распознавание происходит в тот момент, когда соответ-
ствующая процедура заканчивает свою работу с признаком ус-
пешного завершения. Таким образом, в процессе грамматиче-
ского разбора всегда будет сначала распознан идентификатор
VALUE в качестве нетерминального символа <id — list), а уже
потом предложение в целом будет распознано в качестве нетер-
минального символа (read).
На рис. 5.12в символически изображен объектный код, ко-
торый должен быть сгенерирован для предложения RLA' •
Этот код представляет собой вызов подпрограммы XREAD, к°
торая должна содержаться в стандартной библиотеке комнн-1'1
тора. Эта подпрограмма может быть вызвана также лю(-к’1
лрограммой, желающей выполнить операцию чтения. Подпоо
грамма XREAD связывается с генерируемой программой связи
вающим загрузчиком или же редактором связей. (Компилятор
должен включить в объектную программу достаточно инфор-
мации для определения всех необходимых связей,
возможно, средства модификации, описанные в гл.
используя,
2.) Подоб-
<id-list> ::= id
{read)
добавить Slid) к списку
увеличить LISTCOUNT на 1
<id-list) 9 id
добавить S<id) к списку
увеличить LISTCOUNT на 1
READ ( <id-list> )
сгенерировать С +JSUB XREAD1
внешние ссылки для XREAD
сгенерировать С WORD LISTCOUNTJ
Гог каждый элемент списка do
begin
удалить G(ITEM) из списка
сгенерировать С WORD S(ITEM)J
end
LISTCOUNT := 0
6.
+JSUB XREAD
WORD 1
WORD VALUE
в
Рис. 5.12. Генерация объектного кода для предложения READ.
пая техника обычно используется при компиляции предложе-
ний, выполняющих относительно сложные функции. Использо-
вание подпрограмм в этом случае позволяет избежать повторной
генерации больших фрагментов программы, что существенно
сокращает генерируемую программу.
Поскольку подпрограмма XREAD может быть использована
Для любых операций чтения, она должна иметь нарамщры,
определяющие детали этой операции. В нашем случае ишеок
параметров подпрограммы XREAD помещается непосреди веын
за инструкцией JSUB, которая ее вызывает. Первое слово в
этом списке параметров содержит величину, 0ПРед^ • 11ение
личество переменных, которым должно быть прнсвос . ,|1Х
в результате осуществления операции чтения. .
словах содержатся адреса этих переменных. Таким обра-
зом, вторая строка на рис. 5.12в определяет, что должно быть
прочитано значение одной переменной, а третья строка содер-
жит ее адрес. Адрес первого слова списка параметров будет
автоматически помещен в регистр L при выполнении инструк-
ции JSUB. Подпрограмма XREAD может использовать этот
адрес для определения своих параметров и, сложив содержимое
регистра L с длиной списка параметров, определить значение
адреса возврата.
На рис. 5.126 представлен набор программ, которые могут
использоваться для генерации объектного кода. Первые две
программы соответствуют двум альтернативам для нетер-
минального символа (id— list) в грамматическом правиле 6 на
рис. 5.2. В любом случае спецификатор лексемы S(id) для
очередного идентификатора, являющегося элементом <id — list),
включается в список, используемый программами генераций
кода. Соответствующая переменная LISTCOUNT увеличивается
на единицу, чтобы отразить включение в список нового иденти-
фикатора. После того как нетерминальный символ <id — list)
будет разобран, список будет содержать спецификаторы лексем
для всех идентификаторов, содержащихся в <id — list). Когда
будет распознано предложение (read), эти спецификаторы лек-
сем будут удалены из списка и использованы для генерации
объектного кода, соответствующего операции чтения READ.
Обратите внимание, что в процессе генерации дерева грам-
матического разбора, изображенного на рис. 5.12а, вначале рас-
познается (id — list), а уже потом (read). На каждом шаге
грамматического разбора вызывается соответствующая програм-
ма генерации объектного кода. Вы должны внимательно про-
анализировать этот пример, чтобы убедиться в правильном по-
нимании процесса генерации объектного кода, символически
представленного на рис. 5.12в с помощью программ генерации
на рис. 5.126.
На рис. 5.13 изображен процесс генерации объектного кода
для предложения присваивания в строке 14 на рис. 5.1. На
рис. 5.13а приведено дерево грамматического разбора этого
предложения. Основная работа при грамматическом разборе
этого предложения состоит в анализе нетерминального символа
(ехр) в правой части оператора присваивания. Как мы видим,
в процессе грамматического разбора идентификатор SUMSQ
распознается сначала как (factor), потом как (term). Далее
распознается целое число 100 как (factor); затем фрагмент
SUMSQ DIV 100 распознается как (term) и т. д. Эта цепочка
шагов примерно совпадает с изображенной на рис. 5.86. Пора-
док распознавания фрагментов этого предложения совпадает 1
порядком, в котором должны выполняться соответствующие nN
.числения; сначала вычисляются подвыражения SUMSQ Dl\
Н MEAN*MEAN, а затем второй результат вычитается из
первого.
Как только очередной фрагмент предложения распознан, вы-
зывается соответствующая программа генерации кода. Предпо-
ложим, что мы хотим сгенерировать код, соответствующий пра-
вилу
(term)! (term)2 * (factor)
Индексы использованы здесь для различения двух вхождений
нетерминального символа (term). Наши программы генерации
кода выполняют все арифметические операции с использовани-
ем регистра Л, и мы заведомо должны сгенерировать в объект-
ном коде операцию MUL. Результат этого умножения <term>( —
после операции MUL сохранится в регистре А. Если либо
<term>2, либо (factor) уже находятся на регистре А (после вы-
полнения предыдущих вычислений), генерация инструкции
M.UL — это все, что нам нужно. Иначе мы должны сгенериро-
вать также инструкцию LDA, предшествующую инструкции
MUL. В этом случае нам также надо предварительно сохра-
нить значение регистра А, если оно понадобится в будущем.
Очевидно, необходимо отслеживать значение, помещенное в
регистр А, после каждого фрагмента генерируемого объектного
кода. Это можно осуществить за счет расширения понятия
спецификатора лексемы на нетерминальные узлы дерева грам-
матического разбора. В только что рассмотренном примере
спецификатору узла S((term)i) будет присвоено значение гЛ,
указывающее на то, что результат этих вычислений содержится
в регистре А. Переменная REGA используется для указания па
самый высокий уровень узла дерева грамматического разбора,
значение которого помещено в регистр А в сгенерированном до
данного момента объектном коде (т. е. указатель па узел, спе-
цификатор которого равен гА). Очевидно, в каждый момент
процесса генерации объектного кода существует ровно один
такой узел. Если же в регистре А нет значения, соответствую-
щего некоторому узлу, то спецификатор этого узла аналогичен
спецификатору лексемы: это либо указатель на переменную (в
таблице символов), содержащую соответствующее значение,
либо указатель на целую константу.
Чтобы проиллюстрировать приведенные соображения, рас-
смотрим программу генерации объектного кода на рис. 5.136,
соответствующую правилу
(term)! (term)2 * (factor)
Если спецификатор узла какого-либо из операндов равен гА,
то соответствующее значение уже содержится в регистре А и
программа генерирует только одну инструкцию MUL. Адрес
операнда для инструкции MUL содержится в спецификаторе
(assign)
<assign> ::= xd := <exp>
GETA (<exp>)
сгенерировать t STA S<id)l
REGA := null
/pxd> ::= <term>
S(<exp>) := S(<term>)
if S(<exp)> = гA then
REGA := <exp>
<зхр>1 ::= <exp>2 + <term>
if S(<exp>2) = rA then
сгенерировать C ADD S(<terw>)J
else if S(<term>) = rA then
сгенерировать C ADD S(<exp>2)3
else
begin
GETA (<exfr>2)
сгенерировать C ADD S(<ter«>)3
end
$(<exp>l) s= rA
REGA Iя <exp>l
<ехр>1 ц. ..xp?2 - <tera>
if S((exp)2) » rA then
сгенерировать C SUP S(<terM>)l
else
begin
GETA (<exp>2)
сгенерировать C SUB S<<tcrm>)J )
end
S((exp>l) := rA
REGA s- <CHP>1
Clere) l»« (factor)
S((ter*i>) ja S(<factor>)
if S((term)> = rA then
REGA j= (tcra)
<term)l ::= (terM>2 « (factor)
if S((ter«)2) = rA then
сгенерировать C MUL 8(<factor>)3
else if S((factor)) «= rA then
сгенерировать C MUL S((teTM)2)l
else
begin
GETA ((ter«>2)
сгенерировать C MUL S((factor))J
end
S((tern»)l) s» rA
REGA :=» (terat)l
(ter«)l il« (ler»>2 DIV (factor)
if S((ter»>2) = rA then
сгенерировать C DIV S(<factor>'‘?
else
begin
GETA <(terM>2)
сгенерировать t DIV SC<factor)>3
end
S((tere)l) i- rA
REGA I- (tere)l
(factor) ijs id
S((factor)) ;= S(id)
(factor) IX’ int
S((factor)) is S(int)
(factor) II’ ( (exp) >
SUfactor)) := S((eHp)> &
• •
procedure GETA (NODE)
begin
if REGA « null then
сгенерировать C LDA S(N0DE>3
else if S(NODE) « rA then _
begin
породить новые рабочие переменные П
сгенерировать С STA TiJ
ссылки вперед на Ti
S(REGA) := Ti
.сгенерировать С LDA. S(NODE>3
end (if rAj
S(NODE) s* rA
REGA i« NODE
end CGETA) ’
& Зак, 792
LDA SUMSQ
«100
STA Tl
LDA MEAN
MUL MEAN
STA T2
LDA Tl
SUB T2
STA VARIANCE
2
Рис. 5.13. Генерация объектного кода для предложения присваивания.
узла другого операнда (значение которого не находится на ре-
гистре А). В противном случае вызывается процедура GETA
Эта процедура, изображенная на рис. 5.13в, генерирует инст-
рукцию LDA для загрузки значения, связанного со значением
<term>2, в регистр А. Дополнительно перед инструкцией 1.DA
процедура генерирует инструкцию STA для сохранения текуще-
го значения регистра А, если только REGA не нуль (равенство
REGA нулю означает, что это значение больше не понадобит-
ся). Это значение запоминается в некоторой рабочей перемен-
ной. Рабочие переменные образуются в процессе генерации
объектного кода (с именами Tl, Т2, ...) по мере необходимо-
сти. Для используемых компилятором рабочих переменных бу-
дет отведено место в конце объектной программы. На узел
дерева грамматического разбора, связанный со значением, содер-
жащимся в регистре А, указывает переменная REGA. Специфи-
катор этого узла модифицируется, чтобы указывать на рабочую
переменную, используемую для хранения этого значения.
После того как все необходимые инструкции сгенерированы,
программа генерации кода устанавливает спецификатор S
(<term>i) и переменную REGA таким образом, чтобы было вид-
но, что значение, соответствующее <termi>, находится в настоя-
щее время в регистре А. На этом процедура генерации кода
для операции * завершается.
Программа генерации кода, соответствующая операции
практически совпадает с только что рассмотренной програм-
мой для операции *. Программы для D1V и — также апа. »-
гичны, за исключением того, что для этих операций необходи м >,
чтобы на регистре А был установлен именно первый опери
Программа генерации кода для операции присваивания
состоит в загрузке присваиваемой величины на регистр <
использованием GETA) и генерации инструкции STA. / у
внимание, что переменная REGA потом обнуляется, ПОС1‘; '‘’ ’0
код, соответствующий предложению присваивания, полное
сгенерирован и все промежуточные результаты больны
нужны., -)у10Т
Оставшиеся правила, показанные на рис. 5.136, не тры.
генерации каких-либо машинных инструкций, поскольку 1,1
соответствуют никаким вычислениям или перемещениям тш
НЫХ. Программы генерации кодов для этих правил должны со"
ответствующим образом установить спецификатор для узла са-
мого верхнего уровня, чтобы он указывал на ячейку, содержа-
щую соответствующее значение.
На рис. 5.136 представлено символическое изображение
объектного кода, сгенерированного для предложения присваива-
ния. Вы должны внимательно проследить генерацию этого кода
чтобы понять механизм работы программ на рис. 5.136 и 5.1 Зв.
Вам надо также проверить, что эти коды действительно выпол-
няют те вычисления, которые записаны в предложении исход-
ной программы.
На рис. 5.14 изображены другие программы генерации кода
для грамматики рис. 5.2. Программа для (prog —name5) генери-
рует заголовок объектной программы, аналогичной результату
работы директив ассемблера START и EXTREF. Опа также
генерирует инструкции для сохранения адреса возврата и пе-
рехода на первую выполняемую инструкцию компилируемой
программы. После того как вся программа распознана, резер-
вируется память для рабочих переменных (Ti). Затем все ссыл-
ки на эти переменные фиксируются в объектном коде с исполь-
зованием процедуры обработки ссылок вперед, осуществляемой
однопросмотровым ассемблером. Компилятор генерирует так-
же модифицирующие записи, необходимые для описания внеш-
них ссылок на библиотечные подпрограммы.
Генерация кода для предложения (for) состоит из не-
скольких шагов. После того как распознан нетерминальный
символ (index — ехр), генерируется код для инициализации ин-
дексной переменной цикла и инструкции проверки конца цикла.
Масть информации также записывается в стек для дальнейше-
го использования. Далее независимо генерируются коды для
каждого предложения, составляющего тело цикла. После того
как вся конструкция (for) распознана, генерируется код, уве-
личивающий индексную переменную и осуществляющий воз-
врат на начало цикла для проверки условий его завершения.
Здесь программы генерации кода используют информацию, за-
писанную в стек программой, соответствующей (index ехр).
Использование стека для запоминания этой информации позво-
ляет обрабатывать вложенные циклы (for).
Вы можете проследить весь процесс генерации кода для
этой программы, используя дерево грамматического разоора
Рис. 5.4 в качестве управляющей информации. Результат дол-
жен совпасть с изображенным на рис. 5.15. Еще раз повторим,
Что это всего лишь символическое изображение сгенерирован
«ого кода. Большинство компиляторов генерирует коды не
бедственно на машинном языке.
<ргод} !!= PROGRAM <ргод-паме> VAR <dec-list> BEGIN <stmt-list> END
‘•[/•fl • • • * 4 < Л • • , ।
сгенерировать C 4.DL RETADR3
сгенерировать С RSUB3
Гог каждая используемая переменная Ti do
сгенерировать (Ti RESW 13
Вставить С J EXADDR3 (переход на
первое выполняемое предложение} в
байты 3-5 объектной программы
Сформировать ссылки вперед на переменные Ti
сгенерировать запись-модификатор для внешних ссылок
сгенерировать С END3
(ргод-ламе) io
сгенерировать С START 03
сгенерировать С EXTREF XREADfXURITEl
сгенерировать С STL RETADR3
увеличить LOCCTR на 3 (место для команды
перехода на первое выполняемое предложение)
сгенерировать (RETADR RESU 13
idee-list) 25= (любые альтернативы)
сохранить LOCCTR в качестве EXADDR (адрес
первого выполняемого предложения)
(dec) (id-list) 5 (type)
Гог каждый элемент списка do
begin
исключить SCNAME) из списка
занести LOCCTR в таблицу символов в качестве
адреса NAME
сгенерировать ES(NAME) RESW 11
end
LISTCOUNT := 0
(type) :s= INTEGER
(не нужны никакие действия по генерации кода.'
<sttot-list> 55= (любые альтернативы)
(не нужны никакие действия по генерации кода-
XX® (любые альтернативы)
Сне нужны никакие действия по генерации кода?
(write) и® WRITE «id-list»
сгенерировать С +J5UB XWRITE1
внешние ссылки ДЛЯ XWRITE
сгенерировать С WORD LISTC0UNT3
for каждый элемент списка do
begin
исключить S(ITEM) ИЗ списка
сгенерировать Е WORD S(ITEM)T
end
LISTCDUNT := 0
(for) х:= FOR (index-exp) DO (body)
взять из стека JUHPADDR (адрес команды выхода из цдела)
взять из стека S(INDEX) (индексная переменная)
взять из стека LOOPADDR (адрес начала цикла)
сгенерировать Е LDA S(INDEX))
сгенерировать Е ADD 41)
сгенерировать Г J LOOPADDR]
вставить С JGT LOCCTR) в ячейку JUMPADDR
(index-exp) id s® <exp)l T0(exp)2
БЕТА «ехр>1>
поместить в стек LOCCTR (адрес Начала цикла)
поместить в стек S(id) (индексная переменная)
сгенерировать E STA S(id)J
сгенерировать Е COMP S(<exp>2)3
поместить в стек LOCCTR (адрес выхода из цикла)
увеличить LOCCTR на 3 (место для команды перехода)
REGA ;= null
(body) ss= (любые альтернативы)
(не нужны никакие действия по генерации кода)
рис. 5.14. Другие
на рис, 5.2.
программы генерации объектного кода для грамматики
Строка Символическое представление сгенерированного кода
1 STATS START 0 {заголовок программы)
EXTREF XREAD.XURITE
STL J . RETADR CEXADDR} {сохранение адреса возврата)
RETADR RESW 1
3 SUM RESW 1
SUMSQ RESW 1
I RESW 1
VALUE RESW 1
MEAN RESW 1
VARIANCE RESU 1
S (EXADDR) RESW ♦0 (SUM г= 0)
STA SUK
6 LDA 40 {SUMSQ ;= 0)
STA SUMSQ
7 LDA ♦1 {FOR I 1 TO 100)
COMP 4100
JGT (L2)
{LB STA I
7 +JSUK XREAD {READCVALUE))
WORD 1
WORD VALUE
10 LDA SUM <SUM SUM + VALUE)
ADR VALUE
STA SUM
Я LDA VALUE (SUMSQ':= SUMSQ + VALUE M VALUE)
MUL VALUE
ADU SUMSQ
STA SUMSQ
LDA 1 (конец цикла FOR)
ADU 31
•J <LD
13 <L2) LDA SUM (MEAN s= SUM DIV 100)
HIV- 4100
STA MEAN
14 LDA SUMSQ (VARIANCE;=SUMSQ DIV 100-MEAN*I1EAN)
DIV 3100
STA Tl
LDA MEAN
MUL. MEAN
STA 12
LDA ‘ 11
SUK 12
STA VARIANCE
15 +JSUL XURITE {WRITE(MEAN , VARIANCE))
WORD 2
WORD MEAN
WORD VARIANCE
LDL EETADR {возврат)
Ti RESU •1 {используемые рабочие переменные)
12 RESU END 1
Рис. 5.15. Символическое представление объектного кода, сгенерировало!
для программы на рис. 5.1,
5.2. Машинно-зависимые особенности
компиляторов
В этом разделе мы кратко обсудим некоторые машинно-за-
висимые расширения базовой схемы компиляции, представлен-
ной в разд. 5.1. Целью компилятора является трансляция про-
граммы, написанной на языке программирования высокого уров-
ня, в машинные коды для некоторого компьютера. Большинство
языков программирования высокого уровня построено так, что-
бы быть относительно независимыми от тех машин, на кото-
рых они будут использоваться (хотя достигнутая степень такой
независимости существенно различна для разных языков). Это
означает, что процесс анализа синтаксиса программ, написан-
ных на этих языках, должен быть также машинно-независимым.
Таким образом, неудивительно, что машинно-зависимые осо-
бенности компилятора связаны с программами генерации и
оптимизации объектного кода.
На элементарном уровне можно сказать, что весь процесс
генерации кода является машинно-зависимым, поскольку мы
должны знать систему команд компьютера, для которого этот
код генерируется. Существуют, однако, более сложные пробле-
мы, вытекающие из машинной зависимости, которые возникают
при распределении регистров и перестановки машинных инст-
рукций для повышения эффективности. Такого рода оптимиза-
ция кода обычно осуществляется с использованием промежуточ-
ной формы представления компилируемой программы. В этой
промежуточной форме синтаксис и семантика исходных пред-
ложений программы уже полностью проанализированы, ио
трансляция в машинные коды еще не осуществлена. Анализи-
ровать и модернизировать программу, представленную в такой
промежуточной форме для оптимизации кода, существенно лег-
че, чем для исходной формы программы на языке высокого
уровня или для этой программы, представленной в машинных
кодах.
В разд. 5.2.1 мы приведем одну стандартную форму пред-
ставления программы в промежуточном виде. Она не сильно
зависит от той машины, для которой разрабатывается компи-
лятор. Однако использование этой формы необходимо для об-
суждения машинно-зависимой оптимизации кода в разд. 5.~.~.
Существует также много машинно-независимых методов опти-
мизации кода, которые используют аналогичное промежуточное
представление программы. Некоторые из этих методов мы о
судим в разд. 5.3.
5.2.1. Промежуточная форма представления
программы
Существует много различных способов представления поо
граммы в некоторой промежуточной форме для анапичЯР м
оптимизации кода. См., например, Ахо [1977] и Гоис И9711
Метод, который мы обсудим в этом разделе, состоит в ппол
ставлении выполняемых инструкций программы с помощью по
следовательности четверок {quadruples). Каждая четверка за-
лисывается в виде * 1
операция, opl, ор2, результат
где операция — это выполняемая объектным кодом функция
op 1 и ор2 — операнды этой операции, а «результат» определяет'
куда должно быть помещено результирующее значение.
Например, предложение исходной программы
SUM := SUM + VALUE
может быть представлено четверками следующим образом:
4- , SUM, VALUE, ij
i, , , SUM
Здесь ij обозначает промежуточный результат (SUM +
VALUE); вторая четверка присваивает это значение перемен-
ной SUM. Для обеспечения дополнительных возможностей оп-
тимизации кода присваивание рассматривается как независи-
мая операция (:=). Аналогично предложение
VARIANCE := SUMSQ DIV 100 - MEAN * MEAN
может быть представлено в
следующим образом:
виде последовательности четверок
DIV, SUMSQ, #100, 1,
* , MEAN , MEAN, i2
4 » ii > i2 > 13
1= , i3 , , VARIANCE
Эти четверки могут быть сгенерированы программами гене
рации промежуточного представления (аналогичными тем,
торые были рассмотрены в разд. 5.1.4). Для оптимизации м
эти четверки могут анализироваться и модернизироваться
гими различными способами. Например, можно изменить пор,,
док следования четверок для исключения ненужных опер<
запоминания и загрузки регистров. Промежуточные резульь
О можно запомнить в регистрах или рабочих переменны.
тем чтобы обеспечить их эффективное использование. > 1,1
уперлцмя ОрГ Op 2 результат
(1) fo SUM, {sum :« 0}
• « no SUMSQ {SUMSQ :• 0}
(3) fl I (FOR I 1 TO 100}.
(i) JCT I #100 (15)
(5) CALL XREAD (REAbC VALUE) }
(6) PARAM VALUE
(7) + SUM VALUE (SUH ;• SUM + VALUE)
(8) 4 sum
(9) * VALUE VALUE S2 (SUMSQ SUMSQ + VALUE * VALUE)
,(Ю) SUMSQ J3
<Н) • w SUMSQ
(12) 4- I n *4 { К0Н1Ц ЦИКЛ» FOR)
(13) *4 I
(14) J (4)
(15) DIV SUM #100 45 {MEAN f- SUM DtV 100}
(16) * Ж MEAN
(17) DIV SUMSQ 0100 *6 {VARIANCE :«• SUMSQ DIV 100 - .
(18) A MEAN MEAN S7 MEAN * MEAN)
(19) M J6 4 aa
(20) 1* VARIANCE
(21) CALL *write {WRITtflftAN,VARIANCE)}
(22) JARAM MEAN *
(23) шан VARIANCE
Рис. 5.16. Промежуточная форма представления программы на рис. 5.1.
удим некоторые из этих возможностей в последующих разде-
лах. После осуществления оптимизации на уровне четверок мо-
дифицированная последовательность четверок должна транс-
лироваться в машинные коды.
Обратите внимание, что четверки расположены в том поряд-
е» в котором должны выполняться соответствующие инструк-
ции объектного кода, что существенно облегчает анализ для
оптимизации кода. Это означает также, что трансляция в ма-
шинные инструкции будет относительно простой.
На рис. 5.16 изображена последовательность четверок, соот-
ветствующая исходной программе на рис. 5.1. Обратите внима-
ние что предложения READ и WRITE представлены операцией
'-ALL, за которой следует четверка PARAM, определяющая
параметры операций READ и WRITE. Четверка PARAM будет,
разумеется, при окончательной генерации машинного кода от-
транслирована в список параметров, подобный изображенному
на рис. 5.15. Операция JGT в четверке (4) сравнивает значе-
ние двух своих операндов и осуществляет переход к четвер-
ке (15), если первый операнд больше второго. Операция J в
четверке (14) осуществляет безусловный переход к четвер-
ке (4).
Для того чтобы увидеть соответствие между исходной про-
граммой и последовательностью четверок, вам надо сравнить
рис. 5.16 и 5.1. Вы можете также сравнить последовательность
четверок на рис. 5.16 с изображением объектного кода на
рис. 5.15.
5.2.2. Машинно-зависимая оптимизация кода
В этом разделе мы кратко опишем несколько различных
путей осуществления машинно-зависимой оптимизации кода.
Более подробная информация о методах оптимизации содержит-
ся во многих книгах, посвященных компиляторам, таких как
Ахо [1977] и Грис [1971].
Первая проблема, которую мы обсудим, состоит в назначе-
нии и распределении регистров. Многие компьютеры имеют
несколько регистров общего назначения, которые могут исполь-
зоваться для хранения констант, значений переменных, проме-
жуточных результатов и т. д. Те же регистры часто могут ис-
пользоваться и для адресации (в качестве базовых или индекс-
ных регистров). Мы, однако, рассмотрим лишь использование
регистров в качестве операндов соответствующих инструкций.
Машинные инструкции, которые используют регистры в ка-
честве своих операндов, обычно выполняются быстрее, чем со-
ответствующие инструкции, требующие обращения к памяти.
Следовательно, мы должны стараться разместить на регистрах
все переменные и промежуточные результаты, которые пот< л
будут использоваться в программе. При каждом обращении к
памяти или вычислении промежуточного результата это значе-
ние можно запомнить в каком-либо регистре; тогда оно будет
доступно для последующего использования уже без обращения
к памяти. Мы применили очень простую версию этого мего.ы
в разд. 5.1.4, когда отслеживали значение, находящееся в
ный момент на регистре А.
Рассмотрим в качестве примера последовательность че i
рок на рис. 5.16. Переменная VALUE используется один р>>' •
четверке 7 и дважды в четверке 9. Если бы у нас было
статочно регистров, то можно было бы обратиться за этой д
личиной к памяти только один раз. Ее значение осталось
на регистре для использования в командах, соответствуют
четверке 9. Аналогично четверка 16 запоминает значение i5 в
переменной MEAN. Если сохранить i5 на регистре, то значение
этой переменной может быть использовано, когда в четверке
18 потребуется значение переменной MEAN. Использование
регистров может сделать также ненужным большинство
рабочих переменных. Рассмотрим, например, машинный код на
рис. 5.15, в котором для обработки шести из восьми промежу-
точных результатов (б) на рис. 5.16 достаточно воспользовать-
ся только одним регистром (регистром А).
В действительности, конечно же, редко бывает доступно
столько регистров, сколько бы нам хотелось. Проблема, таким
образом, сводится к выбору регистра, переменная в котором
должна быть заменена при необходимости использовать этот
регистр для какой-либо другой цели. Один из возможных под-
ходов состоит в просмотре программы вперед, чтобы опреде-
лить, когда каждый из регистров будет повторно использовать-
ся. Переменная, которая не потребуется в течении наибольшего
времени, как раз и определит искомый регистр. Если регистр,
на который нужно записать новую информацию, содержит зна-
чение некоторой переменной, уже находящейся в памяти, то
старое значение этого регистра может быть просто затерто.
В противном случае его значение должно быть сохранено в
одной из рабочих переменных. Это одна из функций, осуще-
ствляемая рассмотренной в разд. 5.1.4 процедурой GETA, кото-
рая делает это с помощью рабочих переменных Ti.
При распределении регистров компилятор должен также учи-
тывать операторы передачи управления. Например, четверка 1
на рис. 5.16 присваивает переменной SUM значение 0. Это зна-
чение можно было бы сохранить на некотором регистре для
дальнейшего использования. Когда переменная SUM повторно
используется в качестве операнда в четверке 7, можно было бы
взять это значение непосредственно из регистра. Однако подоб-
ное рассуждение может оказаться неправильным. Операция .1
в четверке 14 передает управление четверке 4. Если управление
передастся четверке 7 именно таким образом, то значение пере-
менной SUM окажется не занесенным на регистр. Это произой-
дет, например, если на этот регистр будет занесено значение
в четверке 12. Таким образом, наличие инструкций перехода
порождает определенные трудности контроля за состоянием ре-
гистров.
Один из способов решения этой проблемы состоит в разбие-
нии программы на линейные участки. Линейным участком явля-
ется последовательность четверок с одной точкой входа, нахо-
дящейся в начале участка, и одной точкой выхода в конце
лилейного участка без каких-либо переходов внутри него. Дру-
гими словами, каждая четверка, иа которую может быть пере-
дано управление в результате операции перехода, или же
четверка, непосредственно следующая за четверкой передачи
управления, начинает новый линейный участок. Поскольку вы-
зов процедуры может оказать непредсказуемое влияние на со-
держание регистров, операция CALL, обычно также рассматри-
вается как начало линейного участка. Распределение и исполь-
зование регистров внутри линейного участка могут быть осу-
ществлены только что описанным методом. Однако, когда
управление передается от одного линейного участка к другому,
для последователь-
ности четверок на
рис. 5.16.
все находящиеся на регистрах значения
упрятываются в рабочие переменные.
На рис. 5.17 изображено разбиение
четверок рис. 5.16 на линейные участки,
Участок А содержит четверки 1—3; уча-
сток В содержит четверку 4 и т. д. Рис. 5.17
можно рассматривать также как струк-
туру операторов передачи управления
программы: стрелка от участка X к уча-
стку Y обозначает, что управление пере-
дается непосредственно от последней чет-
верки участка X к первой четверке участ-
ка Y. (Внутри линейного участка управле-
ние, разумеется, передается последователь-
но от одной четверки к другой в порядке
их расположения.) Такого рода схема на-
зывается блок-схемой программы. В рам-
ках более сложных методов оптимизации
кода блок-схема может стать объектом са-
мостоятельного анализа с целью осуществления распределения
регистров, сохраняющегося при переходе от одного линейного
участка к другому.
Другая возможность оптимизации кода состоит в переупо-
рядочивании четверок перед преобразованием их в машинный
код. Рассмотрим, например, четверки на рис. 5.18а. Они в основ-
ном совпадают с четверками 17—20 на рис. 5.16 и соответсг-
вуют предложению 14 исходной программы на рис. 5.1. На
рис. 5.18а изображен типичный машинный код, сгенерирован-
ный по этим четверкам с использованием одного регистра (ре-
гистра А). Этот код совпадает с кодом, изображенным на
рис. 5.15 для предложения 14.
Обратите внимание, что сначала вычисляется промежуточ
ное значение i’i и запоминается в рабочей переменной 11. ^ -
лее вычисляется значение 1'2. В третьей четверке этой послед0
вательности вычитается значение 1’2 из значения й. Посколькх
значение 1’2 только что вычислено, оно находится на регистра
Однако это никак не удается использовать, поскольку для опс
рации вычитания на регистре должен находиться первый
ранд, а не второй. Следовательно, необходимо запомнить зпа
чение :а в другой рабочей переменной (Т2) и перед вычитанием
загрузить значение переменной Л из рабочей переменной Т1 на
регистр А.
На основании несложного анализа оптимизирующий компи-
лятор может распознать подобную ситуацию и переставить чет-
верки таким образом, чтобы
второй операнд операции вы- div
читания вычислялся перед пер- «
вым. Такая перестановка изо-
бражена на рис. 5.186. Первые
SUMSQ
MEAN
1100
МЕЛА
i
1
t
2
3
1
2
две четверки последователь-
ности поменялись местами
В результате машинный код
будет содержать на две ин-
струкции меньше и будет ис-
пользоваться только одна ра-
бочая переменная вместо двух.
Подобные соображения могут
применяться для перестановки
четверок, вычисляющих опе-
ранды операции деления или
любой другой операции для
машинной инструкции, тре-
бующей строго определенного
порядка операндов.
Другая возможность ма-
шинно-зависимой оптимизации
кода состоит в использовании
специфических характеристик
и инструкций, имеющихся на
вычислительной машине. На-
пример, на ней могут суще-
ствовать специальные инструк-
ции для организации циклов
или способы адресации, позво-
I
VARIANCE
*3
LDA SUMSQ
D1V #100
STA Tl
LDA MEAN
MUL MEAN
STA T2
LDA Tl
SUB T2
STA VARIANCE
й MEAN MEAN *2
DIV SUMSQ 1100 X1
* ч h 4
h 1 variance
LDA ♦ MEAN
MUL MEAN
STA Tl
LDA SUMSQ
DIV #100
SUB Tl
STA- VARIANCE
6
ляющие сгенерировать более Рис. 5.18. Переупорядочнваиие чет-
эффективный объектный код. верок для оптимизации кода.
Компьютеры серии VAX со-
держат машинные инструкции высокого уровня, позволяющие
выполнять такие сложные функции, как вызов процедуры и
преобразование структур данных. Очевидно, что использование
подобных особенностей, если это удается сделать, может суще-
ственно повысить эффективность выполнения объектной про-
граммы.
Некоторые машины, к ним, в частности, относятся опреде-
ленные модели компьютеров серии CYBER, имеют центральный
процессор, состоящий из нескольких функциональных устроищ в.
Для подобных компьютеров порядок расположения машинных
инструкции может повлиять на скорость выполнения поогоам
мы. Последовательно расположенные инструкции, предназна-
ченные для различных функциональных устройств могут в?,
подняться в некоторых случаях одновременно. Для’ того чтпби
воспользоваться этой особенностью, оптимизирующий компипя-
тор для подобных машин можег переставить машинные инст-
рукции объектного кода. Примеры и ссылки можно найти в
Грис [1971],
5.3. Машинно-независимые особенности
компиляторов
В этом разделе мы кратко опишем некоторые особенности
компиляторов, которые в большой мере не зависят от того, для
какой конкретной машины они написаны. Как и в предыдущем
разделе, мы не пытаемся описать все детали, связанные с ре-
ализацией этих особенностей. Их можно найти в цитированной
литературе. При описании устройства компилятора в разд. 5 1
мы имели дело только с простыми переменными, статически
распределенными по ячейкам памяти объектной программы.
В разд. 5.3.1 представлены некоторые альтернативные пум
распределения памяти для компилируемой программ
В разд. 5.3.2 описываются методы работы со структурирован-
ными переменными, такими как, например, массивы.
В разд. 5.3.3 продолжается обсуждение методов оптимиза-
ции кода, начатое в разд. 5.2.2. При этом мы сосредоточимся
на машинно-независимых методах оптимизации машинного
кода. В разд. 5.3.4 обсуждаются проблемы, связанные с ком-
пиляцией блочно-структурированных языков программиров; -
ния, и предлагаются некоторые пути решения этих проблем.
5.3.1. Распределение памяти
В схеме компиляции, предложенной в разд. 5.1 для всех
ременных, определенных программистом, при обработке сои
ветствующих декларативных операторов выделяются ячейки и..
мяти в объектной программе. Рабочим переменным, вк.ио' •
такие, которые используются для хранения адреса возв|к* -
также присваиваются фиксированные адреса внутри npoi р
мы. Этот простой метод распределения памяти обычно иаз1,! \
ется статическим. Он часто используется для языков, под
ных Фортрану, не допускающих рекурсивного вызова процедь
или подпрограмм и не предоставляющих средств динамическ-
распределения памяти во время выполнения программы.
Если же процедуры могут вызываться рекурсивно, как в
Паскале, статическое распределение памяти не применимо. Рас-
смотрим, например, рис. 5.19. На рис. 5.19а программа MAIN
вызывается операционной системой или загрузчиком (вызов
первого уровня). Первое, что делает программа MAIN,— запо-
минает свой адрес возврата, находящийся на регистре L, в
фиксированную ячейку RETADR внутри программы MAIN. На
рис. 5.196 программа MAIN вызывает процедуру SUB (вызов
б в
Рис. 5.19. Рекурсивный вызов процедуры в случае использования статиче-
ского распределения памяти.
второго уровня). Адрес возврата из этого вызова запоминается
в фиксированной ячейке внутри процедуры SUB. Если теперь
процедура SUB вызовет рекурсивно саму себя, как это изобра-
жено на рис. 5.19в, возникнет следующая проблема. Процедура
SUB запомнит адрес возврата для вызова третьего уровня в
ячейке RETADR из регистра L. Это действие приведет к уни-
чтожению адреса возврата для вызова второго уровня. В ре-
зультате окажется невозможным корректный возврат в про-
грамму MAIN.
Аналогичные трудности возникают с любыми другими пере-
менными, используемыми процедурой SUB. При рекурсивных
вызовах внутренним переменным процедуры SUB могут быть
присвоены новые значения, которые уничтожают предыдущие
значения этих переменных, хотя они могут понадобиться при
вызове процедуры SUB второго уровня после возврата из ре-
курсивных вызовов. Этот же вопрос рассматривался в
разд. 4.3.1 в связи с обсуждением рекурсивной макрогенерации.
Стек
Очевидно, что при выполнении рекурсивных вызовов необ-
ходимо сохранять предыдущие значения любых переменных,
используемых в процедуре SUB, включая параметры, рабочие
переменные, адреса возвратов, ячейки для запоминания регист-
ров и т. д. Обычно это осуществляется с использованием дина-
мического распределения памяти. Каждый вызов процедуры
приводит к образованию области инициализации, содержащей
память для всех используемых в процедуре переменных. Если
процедура вызывается рекурсивно, каждый раз образовывается
новая область инициализации. Каждая область инициализа-
ции связывается с определенным уровнем вызова процедуры, а
не с самой процедурой. Область инициализации не удаляется
до тех пор, пока не произойдет возврата из вызова соответ-
ствующего уровня. Начальный адрес текущей области инициа-
лизации обычно находится на базовом регистре, используе-
мом процедурой для адресации своих переменных. В этом
случае все значения переменных, используемые на разных
уровнях вызова процедуры, хранятся независимо друг от
друга.
Обычно области инициализации располагаются в стеке, при-
чем текущая область инициализации — в вершине стека. Это
изображено на рис. 5.20. На рис. 5.20а, соответствующем
рис. 5.19а, вызывается процедура MAIN; ее область инициали-
зации записывается в стек. На базовый регистр В устанавли-
вается начальный адрес этой текущей области инициализации.
Первое слово области инициализации содержит обычно указа-
тель PREV на предыдущую область инициализации в стеке.
Поскольку эта область является первой, указатель имеет нуле-
вое значение. Следующее слово области инициализации содер-
жит указатель NEXT на первое неиспользуемое слово стека,
начиная с которого будет образована следующая область ини-
циализации. Третье слово содержит адрес возврата из вызова
данного уровня; остальные слова содержат значения перемен-
ных, используемые процедурами.
На рис. 5.206 процедура MAIN вызвала процедуру SUB.
В вершине стека образована новая область инициализации, на
начало которой указывает регистр В. Указатели PREV и NEXT
в обоих областях инициализации принимают указанные на ри-
сунке значения. На рис. 5.20в процедура SUB вызывает рекур-
сивно саму себя. В результате образовывается новая область
инициализации для очередного уровня вызова процедуры SUB.
Обратите внимание, что адрес возврата и значения переменных
Рис. 5.20. Рекурсивный вызов процедуры в случае использования автома-
тического распределения памяти.
для вызовов процедуры SUB различных уровней хранятся не-
зависимо друг от друга.
При возврате из процедуры в процедуру верхнего уровня
текущая область инициализации, соответствующая данному
уровню вызова, уничтожается. Указатель PREV в уничтожае-
мой области используется для установки предыдущей области
инициализации в качестве текущей, и работа программы про-
должается. На рис. 5.20г изображено состояние стека после
возврата из рекурсивного вызова процедуры SUB. Регистр В
указывает на начало области инициализации предыдущего
уровня вызова процедуры SUB. Адрес возврата и значения всех
переменных в этой области инициализации в точности те же,
что и были до рекурсивного вызова.
Этот метод часто называют методом автоматического рас-
пределения для того, чтобы отличить его от других методов
динамического распределения памяти, которые осуществляются
под управлением программиста. При использовании автомати-
ческого распределения памяти компилятор должен генерировать
код для ссылки на переменные с использованием каких-либо
способов относительной адресации. В нашем примере компиля-
тор связывает с каждой переменной адрес, являющийся относи-
тельным адресом в области инициализации, вместо адреса
ячейки внутри объектной программы. Поскольку в соответствии
с принятым соглашением адрес начала текущей области иници-
ализации находится на регистре В, то ссылка на переменную
транслируется как инструкция с использованием относительной
адресации по базовому адресу. Смещением в этой инструкции
является относительный адрес переменной по области инициа-
лизации.
Компилятор должен также сгенерировать некоторый допол-
нительный код для управления областями инициализации.
В начале каждой процедуры должен содержаться код, образу-
ющий новую область инициализации, связывающий ее с пре-
дыдущей областью и устанавливающий необходимые указатели,
как это изображено на рис. 5.20. Этот код часто называется
прологом (prologue) процедуры. В конце процедуры должен
содержаться код, уничтожающий текущую область инициали-
зации и переставляющий соответствующим образом все указа-
тели. Этот код часто называется эпилогом (epilogue).
При использовании метода автоматического распределен '
памяти память для всех используемых в процедуре перемен-
ных выделяется в момент вызова процедуры. Другие метон
динамического распределения памяти дают программисту 'и’
можность самому определить тот момент времени, когда tie1"'
торая память будет выделена. В ПЛ/1, например,
ALLOCATE (А)
» исходной программе транслируется в коды, которые выделяют
память для переменной А. Предложение
FREE (А)
освобождает память, занятую под А в предыдущем предложе-
нии ALLOCATE. Это средство называется управляемым рас-
пределением памяти в ПЛ/1. Когда переменная образуется в
результате выполнения оператора ALLOCATE, она автоматиче-
ски становится доступной для использования в программе. Па-
мять, выделенная под эту переменную в результате предыдущих
операторов ALLOCATE, если они были, сохраняется в стеке и
восстанавливается после освобождения текущей выделенной
памяти.
Другой тип динамического распределения памяти использу-
ется в Паскале. Предложение
NEW(P)
выделяет память для переменной и устанавливает указатель Р
на только что образованную переменную. Тип вновь образован-
ной переменной определяется описанием указателя Р в про-
грамме. Образованная переменная используется в программе
также с помощью указателя Р. Предложение
DISPOSE(P)
освобождает память, отведенную под переменную, на которую
ранее указывал Р. Подобные средства доступны также в ПЛ/1,
где они называются базированным распределением памяти.
Переменная, образованная динамически с использованием
оператора NEW, не занимает фиксированной ячейки в области
инициализации и, следовательно, не может быть адресована не-
посредственно с использованием относительной адресации по
базовому адресу. Доступ к таким переменным обычно осуще-
ствляется с помощью косвенной адресации через указатель на
переменную Р. Поскольку сам указатель занимает некоторую
фиксированную ячейку в области инициализации, он может
быть адресован обычным способом. Аналогичный метод приме-
няется для управляемого распределения памяти в ПЛ/1. Об-
ласть инициализации содержит указатель, который использует-
ся для указания на память, выделенную в результате послед-
него выполнения оператора ALLOCATE.
Пока мы не обсуждали механизм выделения новой памяти для
переменной. Один из подходов состоит в том, что на операцион-
ную систему возлагается функция по распределению всей памя-
ти. Операторы NEW или ALLOCATE транслируются в запрос
и операционной системе для получения области памяти требуе-
мого размера. Другой метод состоит в выделении необходимом
памяти с помощью библиотечных процедур компилятора.
В начале работы программы выделяется большой блок свобод-
ной памяти, которая далее распределяется библиотечными про-
цедурами, использующими некоторый стандартный метод рас
пределения памяти. Дальнейшее обсуждение и оценка метотов
распределения памяти содержится в Стендищ [1980].
Динамическое распределение памяти, рассмотренное в этом
разделе, представляет собой другой пример отсроченного свя-
зывания. Связь адреса с соответствующей переменной осуществ-
ляется во время выполнения процедуры, а не во время компиля-
ции или загрузки. Такое отсроченное связывание обеспечивает
большую гибкость использования переменных и процедур. Этот
метод, однако, требует больших накладных расходов, связанных
с образованием областей инициализации, а также с использо-
ванием косвенной адресации. (Аналогичные соображения были
высказаны в конце разд. 3.4.2 в связи с динамическим связы-
ванием.)
5.3.2. Структурированные переменные
В этом разделе мы кратко обсудим компиляцию программ,
использующих структурированные переменные, такие как мас-
сивы, записи, строки и множества. Прежде всего мы сосредо-
точимся на распределении памяти для подобных переменных и
на генерации кода для доступа к ним. Эти вопросы достаточно
подробно обсуждаются в применении к массивам. Тс же прин-
ципы, однако, могут быть использованы и для других типов
структурированных переменных. Дальнейшие детали, связан-
ные с этими проблемами, содержатся в ряде учебных пособии
по компиляторам, таких как Ахо [1977] и Грис [1971].
Рассмотрим прежде всего описание массива в языке Пас-
каль:
А : ARRAY[1. .10] OF INTEGER
Если каждая переменная типа INTEGER занимает одну
памяти, то мы, естественно, должны выделить 10 слов для '
нения этого массива. В более общем случае, если массив
сан как
ARRAY[/..w] OF INTEGER
мы должны выделить под этот массив и — I + 1 слов
Распределение памяти для многомерных массивов нс с.
сложнее. Рассмотрим, например, двумерный массив
В : ARRAY[0..3, 1..6] OF INTEGER
Здесь первый индекс может принимать 4 различных ввв
(0—3), второй индекс может принимать 6 различных
Следовательно нам требуется 4 * 6 = 24 слова для хранения
этого массива. В общем случае, если массив описан как
ARRAYS..Ир OF INTEGER
требуемое количество слов памяти определяется выражением
(«! — /j 4~ I) * («2 — ^2 + О
Для rz-мерного массива требуемое количество слов определится
в результате произведения п соответствующих множителей.
Рассмотрим теперь вопрос генерации кода для доступа к
массиву. Для этого существенно знать соответствие между эле-
ментами массива и ячейками выделенной памяти. Для одномер-
ных массивов это соответствие очевидно. Если для определен-
ного ранее массива А первое слово будет содержать элемент
А [1], то второе слово — А [2] и т. д. Для массивов большей
размерности, однако, выбор необходимого соответствия не столь
ясен.
0.110 2 [ 0,3 [ 0.4 [ 0.5 | 0.611.1 [ 1.2 [ 1,3 [ 1.4 [ 1,511 6 | 2,11 2.2 [ 2.31 2.4 [ 2.51 2.6 3.1 3.2 3.3 3.4 3.513.61
д
Л
Строк» 0
Строка 1
Строка 2
Строка 3
1.2 2.2 3.2 0.3 1.3 2.3 3.3 0.4 1,4 2.4 3.4 0.5 1.5 2.5 3.5 0.6 1.6 2.6 3.6
а
1------------
Столбец 1
________II________________/I_______________д________v_______л__________ .
Столбец 2 Столбец 3 Столбец 4 Столбец 5 Столбец 6
6
Рис. 5.21. Хранение массива В : ARRAYfO ... 3, 1 .. 6]: а—по строкам и б
по столбцам.
На рис. 5.21 изображены два способа хранения ранее опре-
деленного массива В. На рис. 5.21а все элементы массива с
одинаковым первым индексом располагаются в последователь-
ных ячейках. Такой порядок расположения называется распо-
ложением по строкам. На рис. 5.216 все элементы с одинако-
вым вторым индексом расположены вплотную друг к другу.
Такое расположение называется расположением по столбцам.
Другой способ описать эти соответствия состоит в том, чтобы
последовательно перебирать все слова отведенной под массив
памяти и рассматривать соответствующие изменения индексов.
При расположении по строкам правый (второй) индекс изме-
няется быстрее. При расположении по столбцам быстрее из-
меняется левый индекс. Эти понятия могут быть обобщены на
массивы, имеющие более двух индексов.
Компиляторы для большинства языков высокого сроню
располагают массивы по строкам; именно такого располо \
ния мы будем придерживаться в последующих рассуждениях.
Однако исторически сложилось так, что большинство компилято-
ров с Фортрана располагают свои массивы по столбцам.
Для обращения к элементу массива мы должны вычислить
адрес соответствующего элемента относительно базового адреса
массива. Для обычного компьютера компилятор сгенерирует
код, который разместит этот относительный адрес в индексном
регистре. Далее для доступа к желаемому элементу массива
будет использоваться индексная адресация. В дальнейшем мы
будем предполагать, что базовым адресом является адрес пер-
вого слова памяти, отведенной для хранения массива. Другие
возможности рассмотрены в Ахо [1977].
Рассмотрим сначала одномерный массив
А : ARRAY[1..1O] OF INTEGER
и предположим, что в некотором предложении имеется ссылка
на элемент массива А [6]. Элементу А [6] предшествуют пять
элементов массива; на машине УУМ каждый элемент занимает
три байта. Таким образом, адрес элемента А [6] относительно
начального адреса массива будет равен 5*3=15.
Если индексами элемента массива являются только констан-
ты, вычисление относительного адреса можно осуществить в
процессе компиляции. Если же индексы содержат переменные,
компилятор обязан сгенерировать объектный код, осуществляю-
щий эти операции во время выполнения программы. Предполо-
жим, что массив описан следующим образом:
А : ARRAY[Z..w] OF INTEGER
и каждый элемент массива занимает w байтов памяти. Если
значение индекса есть s, то относительный адрес элемента мас-
сива A [s] определяется выражением
w * (s — 1)
Генерация кода, осуществляющего подобные вычисления, изо-
бражена на рис. 5.22а. Запись A [i2] в четверке 3 означает, что
сгенерированный машинный код должен обращаться к массиву
А с помощью индексной адресации, поместив значение G в ин-
дексный регистр.
Для многомерных массивов генерация кода зависит от спо-
соба хранения массива: по строкам или по столбцам. Мы бу-
дем предполагать, что массивы хранятся по строкам. Рис. 5.21а
иллюстрирует хранение массива
В : ARRAY[0.,3, 1..6] OF INTEGER
по строкам. Рассмотрим сначала элемент массива В [2, 5]. Ec.ni
мы начнем с начала массива, то мы должны пропустить
полные строки (строки 0 и 1), прежде чем окажемся в начале
строки 2 (которая начинается с элемента В [2, 1]) , Каждая и*
кая строка содержит 6 элементов, две строки содержат 2*6 =
= 12 элементов массива. Мы должны также пропустить
первые 4 элемента в строке 2, чтобы добраться до элемента
В [2, 5]. Вместе это составляет 16 элементов массива между
его началом и элементом В [2, 5]. Если каждый элемент зани-
мает три байта, то относительный
адрес внутри массива элемента В А ‘ ARRAY U«.ioi or integer
[2, 5] будет равен 48. •
В более общем случае пред- ,м 5
положим, что массив описан как
В : ARRAYflj. .ulf l2..u2] OF
INTEGER *
(i) -
и мы хотим обратиться к элемен- ( *
ту массива с индексами, имеющи-
ми значения Sj и s2. Относитель- <з>
ный адрес элемента В [sb s2]
I #1 Ч
ч 13
#5 А[121
а
дается выражением
w * {(st — lj) * (u2 — 12 + 1) +
+ (s2 -12)}
Рис. 5.226 иллюстрирует процесс
генерации кода для обращения к
такому массиву. Вы должны вни-
мательно изучить приведенную
последовательность четверок, что-
бы убедиться в том, что вы по-
нимаете изложенные вычисле-
ния.
Приведенные выше методы и
формулы легко могут быть обоб-
щены на массивы большей раз-
мерности. Детали можно найти
в Ахо [1977].
В таблице символов описание
3 : ARRAY 10,.3,1..6] Of INTEGER
ЗИ,J] 5
(1) * I 16
(2) *• J 11 *2
(3) 4- ч i3
(А) * /3
#5 АРД
6
Рис. 5.22. Генерация объектного
кода для доступа к элементам
массива.
массива содержит тип элементов
массива, размерность массива, верхние и нижние границы мас-
сива для каждого индекса. Этой информации достаточно для
того, чтобы компилятор мог сгенерировать код, необходимый
лпя обращения к массиву. В некоторых языках, однако, неоо-
ходимая информация во время компиляции бывает еще не из-
вестна. В ПЛ/1, например, двумерный массив может быть опре-
делен как
Эта запись означает, что первый индекс изменяется от I до
•I 1. а второй индекс находится в пределах от 1 + 1 до J
Здесь I и J-имена переменных, определенных в программе
Очевидно, что для такого массива память можно
о можно отвести лишь
используя какой-либо из методов динамического распределения
памяти. В ПЛ/1 это можно осуществить с помощью'опера-
торя •
ALLOCATE Т
Предполагается, что переменным I и J уже присвоены некото-
рые значения.
Поскольку значения переменных I и J во время компиляции
неизвестны, компилятор не может непосредственно сгенериро-
вать код, подобный изображенному на рис. 5.22. Вместо этого
компилятор образовывает описатель массива, содержащий
ячейки для запоминания верхней и нижней границ всех ин дек-
сов массива. К моменту выделения памяти под такой массив
все границы индексов должны быть вычислены и запомнены в
описателе массива. Для обращения к массиву генерируется код,
использующий необходимые значения из описателя массива для
вычисления требуемого относительного адреса. Описатель мас-
сива может также включать в себя размерность массива, тип
элементов массива и указатель на его начало. Подобная ин-
формация может быть полезна в том случае, когда размещен-
ный в памяти массив требуется передать в качестве параметра
другой процедуре.
Рассмотренные для массивов проблемы также возникают
при компиляции других структурированных переменных (запи-
сей, строк и множеств). Компилятор должен: выделить необхо-
димую для размещения переменной память; запомнить инфор-
мацию, характеризующую структуру переменной; сгенерировать,
используя эту информацию, код для обращения к компонентам
структурированной переменной; породить описатель структури-
рованной переменной для тех случаев, когда необходимая ин-
формация отсутствует во время компиляции. Дальнейшее об-
суждение этих проблем для различных специальных типов
структурированных переменных можно найти в Ахо [1977] и
Грис [1971],
5.3.3. Машинно-независимая оптимизация кода
В этом разделе мы обсудим некоторые важные методы М'1
шинно-независимой оптимизации кода. Так же как и в преды,<
тих разделах, мы не будем стремиться к детальному описан <
какого-либо из этих методов. Вместо этого мы дадим слон^^
описание и проиллюстрируем основные понятия примерами
горитмы и детали, касающиеся этих методов, можно наш
5.3. Маишпио-незав.исимыс особенности компиляторов 281
работах Ахо (1977] и Грис [1971]. Мы будем предполагать
что исходная программа уже оттранслирована в последователь'
ность четверок так же, как в разд. 5.2.1.
Одним из важных источников оптимизации кода является
удаление общих подвыражений, т. е. подвыражений, которые
встречаются в нескольких местах программы и вычисляют одно
и то же выражение. Рассмотрим, например, предложение на
рис. 5.23а. Терм 2*J является общим подвыражением. Опти-
мизирующий компилятор должен только один раз сгенерировать
код, вычисляющий это умножение, и использовать его резуль-
тат в обоих местах.
Общие подвыражения обычно обнаруживаются при анализе
промежуточной формы представления программы. Подобная
промежуточная форма изображена на рис. 5.236. Если мы ис-
следуем эту последовательность четверок, то обнаружим, что
четверки 5 и 12 совпадают, за исключением имени получаемого
промежуточного результата. Обратите внимание также, что
операнд J не меняет своего значения между четверками 5 и 12.
Невозможно достичь четверки 12, нс проходя предварительно
четверку 5, поскольку они расположены на одном линейном
участке. Таким образом, четверки 5 и 12 вычисляют одно и
то же значение. Это означает, что мы можем удалить четверку
12 и заменить любые обращения к ее результату (Йо) иа об-
ращение к переменной i3, которое является результатом четвер-
ки 5 Эта модификация позволяет избежать дублирования вы-
числений подвыражения 2*J, которое мы выделили как общее
подвыражение при анализе исходной программы.
После замены i3 на ii0 мы обнаружим, что четверки 6 и
12 также совпадают, за исключением имени результата. Следо-
вательно, мы можем удалить четверку 13 и заменить перемен-
ную ц всюду, где она используется, на переменную йь Анало-
гично четверки 10 и 11 также могут быть удалены, поскольку
они эквивалентны четверкам 3 и 4.
Результат применения этого метода изображен на рис. 5.23в.
Четверки на этом рисунке перенумерованы, но, чтобы легче
было сравнивать с рис. 5.236, имена промежуточных результа-
тов i] оставлены неизменными, за исключением вышеназван-
ных замен в скобках. Обратите внимание, что общее количество
четверок сокращено с 19 до 15. Поскольку операции во всех
используемых здесь четверках займут, вероятно, примерно оди-
наковое время на обычном компьютере, то мы также сократим
общее время выполнения программы.
Другим источником оптимизации кода является удаление
инвариантов цикла. Так называются подвыражения внутри цик-
ла, результирующие значения которых не изменяются внутри
цикла при переходе от одной итерации к другой. Таким о >•
разом, эти значения могут быть вычислены только один раз
Х.Х t ARRAY] 1..10,1..10] OF INTEGER
FOR X ! I W 10 DO
YLI,2*JJ
a
(1) ; w fl I {ииицйАлнмцил цикла}
(2) JCT I # 10 (20)
(3) •w X «1 *1 {отчисление индексов для х}
<4) * *i i 10 *2
(5) * tz J *3
(6) *3 #1 *4
(7) м *4 fl *5
(8) + iZ *5 *6
(9) * ч #3 *7
(Ю) •• I #1 i8 {вычисление индексе» для Y)
(И) к *8 #10 *9
(12) к iz J *10
(13) *10 #x *11
(14) + *9 *11 *12
(15) к *12 #3 *13
(16) X[17I {операция присваивания)
(17) + #1 I *14 {конец цикла)
(18) *14 I
(19) J (2)
(20) 6 {следующее предложение)
Рис. 5.23. Оптимизация объектного кода, связанная с общими подвыражс-
ннями и инвариантами цикла.
перед входом в тело цикла вместо того, чтобы вычис. > '
заново перед каждой итерацией. Поскольку для болы
программ основное время работы приходится на выпо.
циклов, экономия времени от подобной оптимизации
быть весьма существенной. Мы предполагаем сущест i «
алгоритмов поиска циклов на основе анализа
(ъ 1* fl T <ЙНИЦИ1ЯИЗ*ЦМЯ цмчла}
(2) JGT I /10 (16)
О) •• I fl 4 {^ьни^ленис mhac^qi длд
(4) л ч #10 4
(5) * 12 J 4
(6) Ч #1 Л4
(7) Ч #1 4
(8) 4- i2 4
О) * 4 #3 4
(Ю) + 4 4 Ча {вычисление индексов для Y}
(И) * i12 #3 *13
(12) ; ж Yll13] X [ 1 7 1 •(операция присваивания/
(13) 4- Hl I 414 (конец цикла}
(14) :=» *14 I
(15) J (2)
ая В {следующее предложение/
(1) * #2 J 13 {вычисление инвариантов}
(2) «• 4 #1 4
(3) •м 4 #1 4
(4) • =3 #1 I {инициализация цикла }
(5) JGT I #10 (16)
(б) I #1 4 {вычисление индексов для X/
(7) * 4 #10 i'z
(8) + i2 4 4
(9) * 4 #3 l7
,(Ю) + 4 4 112 .{вычисление индексов для Y }
(И> * i12 #3 *13
(12) VU13 ) x[i7) {операция присваивания }
(13) + 11 I 4. (конец цикла}
(14) • “ J14 I
\(15) J (5) {следующее предложение}
(16) Г
Рис, 5,23, Продолжение.
программы. Одним из примеров подобного алгоритма является
метод построения блок-схемы программы,описанный в разд 5 2
2 < 7 пГрис М5И2Ъ,аР/гмНТоа ЦНКЛЭ является вычисление выражения
2*J на рис. 5.23а (см. четверку 5 на рис. 5.23в). Результат вы-
числения этого выражения зависит только от операнда Ла
чение которого не изменяется во время выполнен^ цима
Таким образом, мы можем поместить четверку 5 на рис 5
непосредственно перед началом выполнения йикла. Аналогичные
соображения справедливы относительно четверок 6 и 7
На рис. 5.23 изображена последовательность четверок яв-
ляющихся результатом описанных модификаций Общее коли-
чество четверок остается тем же, что и на рис 5 23 но коли
честно четверок внутри тела цикла уменьшилось с’14 до и
[Каждое выполнение предложения FOR на рис. 5.23а вызывает
10-кратное выполнение тела цикла. Это означает, что общее
количество операций, необходимых для выполнения FOR, со-
кратилось со 141 до 114.
Наши модификации сократили общее количество операций,
приходящееся на одно выполнение предложения FOR, со 181
(рис. 5.236) до 114 (рис. 5.23г), что существенно уменьшило
время выполнения программы. Существуют также и более тон-
кие методы обработки общих подвыражений и инвариантов
цикла, чем описанные выше. Можно ожидать, что благодаря
этим методам может быть получен еще более оптимизирован-
ный код. Примеры и обсуждение этих методов содержатся в
.работе Ахо [1977].
Некоторую оптимизацию можно, конечно, осуществить путем
переписывания исходной программы. Например, предложения
на рис. 5.23а можно переписать следующим образом:
Т1 := 2*J
Т2 := Т1-1;
FOR I := 1 ТО 10 DO
X [I, 12] := V [I, Т1];
В результате будет достигнута лишь частичная по сравнению
только что описанной оптимизация кода. Дальнейшая оптими-
зация связана с процессом вычисления относительного адреса
индексированных переменных, на которые запись исходной ир
граммы не может повлиять. Например, оптимизацию, 11,1 ,!|
ную с четверками 3, 4, 10 и 11 на рис. 5.236, нельзя (кин
вить путем каких-либо преобразований исходной программ,. •
Следует заметить также, что исходные предложения >
рис. 5.23а предпочтительнее, поскольку они нагляднее, чем
дифицированная версия программы, использующая перемен -
TI и Т2. Оптимизирующий компилятор должен предоста
программисту возможность писать исходную программу
5.3 Матично независимые особенности компиляторов
DO 10 I - 1,20
10 TABLE(I) - 2**1
а
(1) • :« н I (инициализация цикла}
(2) ЕХР I i« •
(вычисление 2*4 jj
(3) м I (вычисление Индексов}
(4) * *2 #3 i3
(5) ; ж TABLEU J w (операция присваивания}
(6) + I #1 i, 4 (конец цикла}
(7) • * *4 I
(8) ЛЕ I #20 (2)
6
(1) ; ж tl 4 (начальные присваивания }
(2) • X #('3) *3
(3) ’ ж #i i {инициализация цикла)
(«Г й dl #2 (вычисление 2**1}
(5) 4- *3 и. i3 (вычисление индексов}
(6) *1 TABLEI131 ^операция присваивания)
(7) 4* I #1 (конец чикла)
(8) :*• J4 I
(9) ЛЕ 1 #20 (4)
Рис. 5.24. Оптимизация объектного кода за счет замены одних операции
иа другие, более эффективные.
чтобы добиваться простоты и прозрачности, должен компили-
ровать программу в машинные коды таким образом, чтобы до-
биться эффективности выполнения.
Еще один источник оптимизации кода состоит в замене ме-
нее эффективных операций на более эффективные. Рассмотрим
в качестве примера фрагмент программы на Фортране, изо-
браженной на рис. 5.24а. Изображенный цикл DO порождает
таблицу, содержащую первые 20 степеней двойки. При каждом
проходе по телу цикла константа 2 возводится в степень 1. На
рис. 5.246 изображено представление этих предложении в виде
последовательности четверок. Возведение в степень представле-
но операцией ЕХР. На уровне машинного кода операция txi
представляет собой либо цикл, осуществляющий последователь-
ность умножений, либо вызов подпрограммы, использующий ло-
гарифмы для получения результата.
Анализируя эту программу, мы можем обнаружить, что су-
ществует более эффективный путь выполнения этих вычисле-
ний. При каждом проходе по циклу величина I увеличивается
на 1. Таким образом, величина 2**1 для текущего прохода
по циклу может быть получена путем умножения на 2 зна-
чения, полученного на предыдущем проходе. Очевидно, что этот
метод вычисления выражения 2**1 является существенно бо-
лее эффективным, чем выполнение серии умножений или ис-
пользование логарифмирования.
Подобные модификации могут быть осуществлены при вы-
числении относительного адреса элемента массива TABLE(1).
Предположим, что каждый элемент массива занимает одно сло-
во, тогда объектная программа для УУМ будет вычислять сме-
щение по формуле 3*(1—1). Это вычисление осуществляется
в четверках 3 и 4 на рис. 5.246. Таким образом, объектная
программа будет выполнять одно умножение при каждом об-
ращении к массиву.
Описанный метод повышения эффективности применим и в
этом случае. Поскольку на каждом проходе по циклу после-
довательно осуществляется обращение к соседним элементам
массива, то вычисление требуемого смещения может быть по-
дучено путем сложения предыдущего смещения с 3. Поскольку
сложение на УУМ происходит быстрее умножения, подобное
преобразование приведет к более эффективному объектному
коду.
На рис. 5.24в приведена модифицированная по* сравнению с
рис. 5.246 последовательность четверок, в которой осуществлены
обе указанные выше возможности повышения эффективности.
Алгоритм, осуществляющий подобные модификации, содержится
в работе Грис [1971]. Как и в нашем предыдущем примере,
подобную оптимизацию можно частично осуществить на уровне
исходной программы. Однако оптимизировать вычисления ин-
дексов массива программист не может, поскольку он не может
влиять на детали кода, генерируемого для обращения к мас-
сиву.
Существует также ряд других возможностей машинно-неза-
висимой оптимизации кода. Например, вычисления знамени
операндов, известных в момент компиляции, могут быть осищ
ствлеиы непосредственно компилятором. Другие методы он -
мизации включают в себя преобразование цикла в линспнн
участок (развертывание цикла) и слияния тел различных ин^
лов. Детали этих и других методов оптимизации см. в I I "1
[1971] и Ахо [1977],
---------^Ма,ци,'^-^ависимыС особенности компиляторов |
5.3.4. Блочно-структурированные языки
В некоторых языках, подобных Алголу, программа пазбш»
ется на части, называемые блоками. Блок - это часть S,
мы, в которой можно описать свои собственные идентифнкато*
ры. Определению блока также удовлетворяют такие программ
ные единицы, как процедуры и функции в Паскале В₽ этом
разделе мы обсудим некоторые вопросы, связанные с компипя
цией и выполнением программ, написанных на таких блочно-
структурированных языках.
На рис. 5.25а изображена схема блочно-структурированной
программы на Паскале. Каждой процедуре соответствует бпок
В последующем обсуждении мы будем' использовать термины
процедура и блок как синонимы. Обратите внимание, что бло-
ки могут вкладываться друг в друга. Например, процедуры В
И D вложены в процедуру А, а процедура С вложена в проце-
дуру В. Каждый блок может содержать, как это изображено
на рисунке, описания переменных. В блоке допустимы также
обращения к любым переменным, которые описаны в любом
блоке, содержащем рассматриваемый блок, при условии что эти
имена не переопределены во внутреннем блоке.
Рассмотрим, например, переменные X, Y, Z типа INTEGER,
определенные в строке 2 процедуры А. Процедура В содержит
описание переменных X и Y, имеющих тип REAL в строке 4.
Внутри процедуры В использование имени X означает ссылку
на переменную типа REAL, определенную внутри В. Однако
использование имени Z означает обращение к переменной типа
INTEGER, определенной в блоке А, поскольку имя Z не пере-
определено внутри В. Аналогично внутри процедуры S имя W
связано с переменной, определенной внутри С; имена X и Y
будут связаны с переменными, определенными в В, и имя Z
связано с переменной, определенной в Л. Переменные не могут
использоваться вне того блока, внутри которого они определе-
ны. Например, именем W нельзя пользоваться вне процедуры
В, а именем V нельзя пользоваться вне процедуры С.
При компиляции программ, написанных на блочно-структу-
рированных языках, удобно нумеровать блоки, как это изо>ра-
жено на рис. 5.25а. Как только распознано начало нового ол -
ка, этому блоку присваивается очередной номер. В 1ХХЛ1'
компилятор может построить таблицу, описывающую . ’>
структуру программы так, как это изображено на рис. . • -
В столбце «Уровень вложенности» содержится глубина, в^ /л
ности блоков. Самый внешний блок имеет уровень в*1 j
1, а все остальные блоки имеют уровень вложе ’ j-j0.
больший, чем уровень вложенности охватываюше - *
скольку имя может быть определено более одно < .Держащий
ных блоках), каждый элемент таблицы символов, содержат
1
2
3
4
PROCEDURE А._____________
VAR X.Y.Z : INTEGER;
procedure в;
VAR W4X,n reAL;
PROCEDURE C;_____
VAR V, W "7 INTEGER;
END (C};;
END {B};
9
10
PROCEDURE D:_______.
VAR : CHAR;
11
END {DE-
12 END. {A}_________________
a
Уровень
Имя Номер вложен- Объемлющий
блока блока ности блок
-—;—; ~'
В 2 2 1
С 3 3 2
D 4 2 1
А
Рис. 5.25. Программа
с вложенными блоками.
5
6
7
8
3
2
4
1
котором этот идентигЬи С°Де₽ЖаТЬ также номер того блока, в
Допустимо если чтг.? 'хатор ?писан' Описание идентификатора
том же блоке В ппг иде”тификатор не был ранее описан в
ла бы несколько - ™ВНоМ случае таблица символов содержа-
Элементы таблипгг п еМеНТ0В’ соответствующих одному имени,
и того же имени R символов> соответствующие описанию одного
собой в таблипр" f блоках’ МОГУТ бьгть связаны между
«ои в таблице символов цепочками указателей.
5 3. Маишнио независимые особенности компилятор
Когда компилятор встречает ссылку на идентпфикатоп
„сходной программе, го прежде всего он должен проверить
лицу символов на наличие описания этого идентиф^опа в
текущем блоке. Если подобное описание отсутствуй компнля
тор должен проверить наличие такого описания в бпоке Т
емлющем текущий, затем в объемлющем блоке еле тую.иХ
уровня и т. д. Если описание этого идентификатора ие'щ.й е , »
даже в блоке самого верхнего уровня, то использование такого
идентификатора является ошибкой.
Только что описанный процесс поиска может быть легко
реализован, если таблица символов построена с использованием
хеширования. Хеш-функция используется для поиска какого-
либо одного определения нужного идентификатора. Далее ком-
пилятор осуществляет поиск необходимого элемента в таблице
символов, идя но цепочке описаний данного идентифика-
тора. Существуют также другие способы организации таблицы
символов, при которых описания соответствующих идентифи-
каторов хранятся с учетом структуры вложенности блоков, в
которых они находятся. Такого рода структуры позволяют
оптимизировать поиск нужного описания. См., например Ахо
11977].
Большинство блочно-структурированных языков использует
автоматическое распределение памяти, описанное в разд. 5.3.1.
Переменные, описанные в данном блоке, располагаются в об-
ласти инициализации, которая порождается заново каждый ра ?
при входе в блок. Если в некотором предложении используется
переменная, описанная внутри текущего блока, то эта перемен-
ная находится в текущей области инициализации и может ис-
пользоваться обычным способом. Однако можно также исполь-
зовать переменные, описанные в некотором объемлющем блоке.
В этом случае для доступа к переменной должна быть найдена
самая поздняя область инициализации того блока, в которой
эта переменная описана.
Один из широко распространенных методов осуществления
доступа к переменным, описанных в объемлющем блоке, ис-
пользует структуру данных, которую мы назовем дисплеем
(display). Дисплей содержит указатель на самую последнюю
область инициализации текущего блока и на все блоки, шн.-
емлющие данный в исходной программе. Если в некотором
блоке осуществляется обращение к переменной, описанной в
некотором объемлющем блоке, то генерируется объектный
который, используя дисплей, ищет область инициализации, 1И
держащую нужную переменную. г п
Использование дисплея иллюстрируется на рис.
полагается, что процедура А вызвана системой. ' J*'1
цедура А вызвала процедуру В? а процедура В вы I
цедуру С. Сложившаяся ситуация изображена на i с.
I область
инициализа-
ции для С
Область
инициализа-
ции для В
Область
инициализа-
ции для А
Стек дисплей
Область
инициализа
ции для В
Область
инициализа
ции для С
Область
инициализа-
ции для D
Область
инициализа-
ции для С
Область
инициализа-
ции для А
D
А
Стек
Дисплей
Область
инициализа-
ции для С
Область
инициализа-
ции для С
Область
инициализа-
ции для В
Область
инициализа-
ции для А
Стек.
— А
Дисплей
Область
инициализа-
ции для В
Область
инициализа-
ции Для D
Область
инициализа-
ции для С
Область
инициализа-
ции для С
Область
инициализа-
ции для В
Область
инициализа-
ции для А
Дисплеи
Стек
С
В
Рис. 5.26г Использование дисплея для процедур, изображенных на рис, 5.25.
Стек содержит области инициализации, соответствующие вызо-
вам процедур А, В и С. Дисплей содержит указатели на об-
ласть инициализации процедуры С и на области инициализации
объемлющих блоков (А и В)..
Предположим теперь, что процедура С вызывает рекурсивно
саму себя, В результате такого вызова в стеке образовываются
новые области инициализации для nDoiienvnM г п
в С переменные должны теперь бып' оа/полпжЛСе ОПНсанн«е
следней области инициализации; указатепь на сВ ЭТОЙ по‘
в дисплее, должен быть также модифицирован ’ <п°держащни^<
ременные, соответствующие предыдущему вызову процед™,"с
не доступны в данный момент, то дисплей не содерж^Т,,»’
ГаЛрисНа5Э26б. ииициализации- Эта ситуации Р„зо6раже„а
Предположим теперь, что процедура С вызывает npoueavnv
D. (Это допустимо, поскольку процедура D определена в пп0У
цедуре А, содержащей С.) Получившееся в результате такого
вызова содержимое стека в дисплее изображено на рис 5 “>6в
Область инициализации для процедуры В образована обычным
образом и записана в стек. Обратите внимание, что дисплей
содержит в этот момент только два указателя: на’ области ини-
щщдзедии процедур J) и А. Это объясняется тем, что про-
цедура D не миЯ?£Т исТюЛьзовать переменных, описанных в В
или С (за исклк5че!1Пбм случая, когда они переданы ей как
параметры), даже несмотря на то, что она вызвана из С,
В соответствии с правилами вйдимбСтй для блочно-структури-
рованных языков процедура D может использовЗТв -тгдько пе-
ременные, описанные в D или в объемлющем D блоке исход-"
ной программы (которым в нашем случае является процеду-
ра А).
Сходная ситуация, изображенная на рис. 5.26г, образуется,
если теперь процедура D вызовет В. Процедура В может ис-
пользовать только те переменные, которые описаны в В или в
А, что и отражено в списке указателей, находящемся в дис-
плее, После того как процедура В завершится и передаст уп-
равление процедуре D, содержимое стека и дисплея опять ока-
жется таким, как на рис. 5.26в.
Важно все время помнить о разнице между динамическим
выделением памяти для переменных, которое соответствует об-
ластям инициализации в стеке, и правилами доступа к пере-
менным в блочно-структурированной программе, которые отра-
жает содержимое дисплея. Вы должны внимательно изучить
рис. 5.25 и 5.26 для того, чтобы убедиться, что вы действитель-
но понимаете, почему стек и дисплей будут иметь именно то
содержимое, какое изображено на этих рисунках.
Компилятор для блочно-структурированного языка должен
содержать в себе код, используемый в начале каждого ло
лля инициализации дисплея, соответствующего да,,ном^ '
В конце блока он должен обращаться к коду, воссг‘
тему предыдущее содержимое дисплея. Детали реализ ц
держатся в Ахо [1977].
5.4. Варианты построения компиляторов
В этом разделе мы рассмотрим некоторые возможные аль-
тернативы построения компиляторов. Изложение будет по не-
обходимости довольно кратким. Наша цель — ввести основные
понятия и концепции, а не подробно обсуждать какие-либо во-
просы.
В разд. 5.1 была описана простая однопросмотровая схема
компиляции. В разд. 5.2 и 5.3 представлены особенности ком-
пиляторов, требующие для своей реализации более одного про-
смотра. В разд.’5.4.1 мы кратко обсудим общую проблему раз-
биения процесса компиляции на отдельные просмотры и рас-
смотрим преимущества однопросмотровых и многопросмотровых
вариантов построения компиляторов.
Разд. 5.4.2 посвящен интерпретаторам, которые преобразуют
исходную программу в некоторую промежуточную форму и вы-
полняют ее вместо трансляции в машинные ЕдТй. о тлГ!ТуГо-’
щем разд. 5.4.3 мы вводим связанное интерпретаторами по-
нятие компилятора на псевдокод, кот<ф‘ый преобразует програм-
мы на языках высокого урС’ия в объектные коды некоторой
гипотетической ^с’шины.
к заключительном разд. 5.4.4 описываются системы построе-
ния" компиляторов, использующие программные средства для
автоматизации многих этапов процесса создания компилятора.
5.4.1. Разбиение на отдельные просмотры
В разд. 5.1 была описана простая однопросмотровая схема
компиляции с подмножества языка Паскаль. Ее основу состав-
ляет процесс грамматического разбора. Лексический сканер вы
зывается, когда для грамматического разбора требуется очеред-
ная входная лексема; обращение к программам генерации объ-
ектного кода происходит как только распознана очередная кон-
струкция языка. Получаемый таким образом объектный код н--
достаточно эффективен, поскольку большинство рассмотренных
в разд. 5.2 и 5.3 приемов оптимизации не применимо в одно-
просмотровых компиляторах. С другой стороны, процесс ком-
пиляции, требующий только одного просмотра по программе и
не осуществляющий преобразований программы в промежуточ-
ные представления, является весьма быстрым.
Не все языка допускают однопросмотровую компиляции’
Описания переменных в Паскале должны предшествовать опе-
раторам, использующим эти переменные. В Фортране перемен-
ные могут быть описаны только в начале программы; тип не-
описанных переменных определяется по умолчанию. Некоторые
языки, в частности ПЛ/1, допускают появление описаний иле11'
тификаторов после их использования. Однопросмотровые ком-
-
29S
5 ссылки впеп^п w г
пцлягоры могут обрабатывать
рехода, используя приемы с
просмотровых ассемблеров’ ГооаГГп г? °П
представляет собой использование эп₽м? «Разную проблему
которых еще не появились. элементов данных, описаний
| Рассмотрим, например, следующий опеоатоп
X := Y*Z оператор присваивания:
Если все переменные X, Y и Z целого типа то обт,Р.-т
дом этого оператора могут быть команда пел^ЛХ,М'
женин и команда запоминания результата Р,Д "’'° »'“"<'
менные целого типа, а другие веЩестве>шого оX,"X
коде должны присутствовать как минимум о на
образования типа и команда умножения с плавающей'точкЙ’
Очевидно, что компилятор не сможет скомпилировал' пр™™!
нып объектный код до тех пор, пока ему не Станут Хет,и
типы всех переменных. Для некоторых сочетании типов nene
^мённых оператор может оказаться вообще недопустимым Ти*
КИМ образом, язык, разрешающий использование элементов дни.
ных до их описания, не допускает однопросмотровой компи-
ляции,
Некоюрые языки программирования по другим причинам
требуют при компиляции более двух просмотров. Например,
Хантер [1981] показал, что Алгол-68 требует как минимум трек
просмотров.
Существует несколько факторов, которые должны учиты-
ваться при выборе однопросмотровой или многопросмотровой
схемы компиляции (в предположении, что рассматриваемый
язык в принципе допускает однопросмотровую компиляцию).
Если важна скорость компиляции, то однопросмотровая схема
может оказаться предпочтительней. Например, при счете сту-
денческих задач большая часть времени, как правило, уходит
на компиляцию. Полученные во время компиляции объектные
модули используются лишь один-два раза; время счета студен-
ческих задач обычно мало. Ускорение процесса компиляции в
этих условиях может привести к существенному повышению
эффективности использования ЭВМ и к сокращению премии
между повторными выходами на машину.
Если же скомпилированные объектные модули исш-.тьо о
многократно или эти модули обрабатываю! <ю-,ь111‘|< „ сУ(
Данных, то скорость выполнения программы случае
важным фактором, чем скорость ее компиляции. ‘ схема
предпочтительнее может оказаться mhoiопрос о | технику
компиляции, позволяющая использовать оолее слi > ^омпилято.
оптимизации объектного кода. Многопросмо> || > оператнвная
ры используются также тогда, когда дос ограннчены.
память и другие ресурсы системы существенно [
VAX является виртуальная память, а управление ею — одним
из наиболее интересных свойств операционной системы
VAX/VMS.
Вся виртуальная память VAX/VMS состоит из 232 байт
и делится на адресное пространство системы и адресное про-
странство процессов размером 231 байт каждый. Адресное про-
странство системы распределяется между всеми процессами,
однако каждый процесс пользователя имеет и свое собственное
адресное пространство. Оно в свою очередь делится на про-
граммную область и область управления. В первой из них на-
ходится программа, выполняемая процессом в текущий момент
Вторая отведена под системные стеки и прочую информацию'
используемую операционной системой.
Виртуальная память состоит из 512-байтовых страниц. Су-
ществует системная таблица страниц, которая содержит по
одному входу для каждой страницы адресного пространства
системы. По нему можно судить, загружен ли соответствующий
ей страничный кадр или нет. Начальный адрес и длина табли-
цы задаются в двух специальных регистрах. Адресное простран-
ство процессов описывается двумя таблицами страниц: одной
для программной области, другой для области управления.
Таблицы располагаются в адресном пространстве системы и са-
ми могут участвовать в страничных операциях. Программы уп-
равления памятью также используют таблицу, содержащую ин-
формацию о состоянии всех страничных кадров в памяти, всех
виртуальных страниц в системе н об их размещении.
По страничному прерыванию активизируется системная про-
грамма, называемая pager. Она выбирает подходящий странич-
ный кадр и переписывает требуемую виртуальную страницу в
память. Для каждого процесса число страниц, одновременно
находящихся в памяти, ограничено. Когда достигается их пре-
дельное число, pager выбирает страницу для выталкивания из
памяти. Максимальное число страниц для каждого процесса
устанавливается динамически и зависит от частоты происходя-
щих в нем страничных прерываний.
Измененные страницы, выталкиваемые из памяти, нс пере-
носятся во внешнюю память сразу. Вместо этого они заносятся
в так называемый список, измененных страниц. Чтобы миними-
зировать накладные расходы, связанные со страничным обме-
ном, pager пытается записывать страницы кластерами (т. е. по
несколько страниц за одну операцию записи).
Если страница из этого списка запрашивается до того, как
она в действительности записана, то для ее восстановления нс
требуется выполнения какого-либо физического ввода-вывода.
Аналогично неизмененные страницы, выбранные для откачки,
заносятся в список свободных страниц. Если входящая в него
страница потребуется до того, как страничный кадо был заново
Ресурсы, требуемые для каждого просмотра, могут быть умень-
шены с увеличением количества просмотров.
На выбор схемы компилятора влияют также и другие Фак-
торы. Если компиляция разбита на несколько просмотров4 то
каждый просмотр упрощается и, следовательно, становится лег-
че для понимания, программирования и отладки. Разработка
отдельных просмотров может быть поручена разным програм,
мистам, которые могут работать параллельно. В результате
уменьшается общее время, требуемое на разработку компиля-
тора.
Дальнейшее обсуждение вопроса о разбиении компиляции
на отдельные фазы можно найти в работах Хантер [1981]
Ахо [1977]. Примеры реальных компиляторов и детальное опи-
сание разбиения всей работы на отдельные этапы содержатся
в книгах Грис [1977] и Ахо [1977].
5.4.2. Интерпретаторы
Так же как и компилятор, интерпретатор обрабатывает ис-
ходную программу, написанную на языке высокого уровня. Ос-
новное различие состоит в том, что интерпретатор непосредст-
венно исполняет некоторое представление исходной программы,
а не транслирует его в машинные коды.
Интерпретаторы обычно выполняют, подобно тому как это
было описано для компиляторов, лексический и синтаксический
анализ и транслируют исходную программу в свое внутреннее
представление. При этом возможно использование самых раз-
личных внутренних представлений. Одно из них — это последо-
вательности четверок, подобные описанным в разд. 5.2. Чаще
используется расширенная польская постфиксная запись (см.
Грис [1971]). В качестве внутреннего представления можно ис-
пользовать даже исходную форму записи программы, хотя
обычно гораздо более эффективной является предварительная
обработка исходной программы, предшествующая се выпол-
нению.
После трансляции исходной программы во внутреннее пред-
ставление интерпретатор выполняет заданные ею операции. На
фазе выполнения интерпретатор можно рассматривать как на-
бор подпрограмм. Вызов этих подпрограмм осуществляется под
управлением внутреннего представления программы.
Трансляция исходной программы в некоторое внутреннее
представление проще и быстрее, чем компиляция в машинные
коды. Однако выполнение интерпретатором внутреннего пред-
ставления программ осуществляется гораздо медленнее, чем вы-
полнение машинных кодов, сгенерированных компилятором.
Таким образом, интерпретатор обычно не следует использован-
когда важна скорость выполнения программы. Если же важнее
оказывается скорость трансляции и время выполнения програм-
мы невелико, то предпочтение может быть отдано интерпрета-
тору.
Существенное преимущество интерпретатора по сравнению с
компилятором состоит в тех средствах отладки, которые легко
могут быть в нем реализованы. Интерпретатор обычно имеет
таблицу идентификаторов, номера строк и другую информацию
об исходной программе. Она может быть использована Ъб вре-
мя выполнения программы для автоматической распечатки по-
именованных данных, трассировки операторов исходной про-
граммы с указанием номеров строк, в которых они содержатся,
и т. д. Следовательно, особенно привлекательным является ис-
пользование интерпретатора в учебном процессе, когда акцент
делается на понимание и отладку программ. Детали, относя-
щиеся к реализации отладочных средств в интерпретаторах,
можно найти в работе Грис [1971].
Большинство языков программирования может достаточно
успешно как интерпретироваться, так и компилироваться. Не-
которые языки весьма хорошо приспособлены для интерпрета-
ции. Как мы уже видели, компиляторы обычно генерируют об-
ращения к библиотечным программам для выполнения таких
функций, как ввод-вывод и сложные операции преобразования
данных. Для таких языков, как Снобол и АПЛ, большая часть
скомпилированной программы состоит из обращений к таким
библиотечным программам. В подобных случаях интерпретатор
может оказаться предпочтительней из-за большей скорости
трансляции. Основное время выполнения программы будет
занимать работа стандартных библиотечных программ неза-
висимо от того, используется ли компилятор или иитерпре-
Татбр»
Особенности некоторых языков могут быть естественно ре-
ализованы только в режиме интерпретации. В языках АПЛ и
Снобол тип переменной может меняться во время выполнения
программы. В АПЛ переменные, доступные внутри функции или
подпрограммы, определяются динамически последовательностью
вызовов во время выполнения программы, а не статической
вложенностью блоков исходной программы (см. рис. 5.25 и 5.26,
иллюстрирующие это различие). Языки, допускающие динами-
ческое переопределение типов и областей действия имен, очень
трудно эффективно компилировать. Их проще реализовать в
режиме интерпретации, который позволяет легко связывать
символические имена переменных с типами данных и ячейками
памяти в ходе выполнения программы.
Дальнейшее обсуждение разработки и использования интер-
претаторов имеется в работе Грис [1971].
5.4.3. Компиляторы на Р-код
Основные идеи, положенные в основу компиляторов на псев-
докод (P-код) и интерпретаторов, весьма схожи. В обоих слу-
чаях исходная программа анализируется и преобразуется во
внутреннее представление, которое затем выполняется в режи-
ме интерпретации. В случае компиляторов на P-код форма
внутреннего представления является машинным языком неко-
торой гипотетической ЭВМ, часто называемой псевдомашиной,
Процесс использования компиля-
тора на P-код изображен на
рис. 5.27. В результате компнля-
Рис. 5.27. Компиляция и выпол-
нение программы с использова-
нием компилятора иа -Р-код.
ции получается объектная про-
грамма в P-кодах. Далее эта про-
грамма читается и выполняется
интерпретатором Р-кода.
Основным достоинством тако-
го подхода является легкая пе-
реносимость программного обес-
печения на другие типы ЭВМ.
Компилятору нс нужно генериро-
вать разные машинные коды для
разных ЭВМ, поскольку объект-
ные программы на псевдокоде
могут выполниться на любой
ЭВМ. имеющей. пнтерпрётйтор
P-кода. Сам компилятор тоже мо-
жет быть перенесен на другие
ЭВМ, если он написан на своем собственном входном языке.
Для этого исходная программа компилятора должна быть ском-,
пилирована на Р-К^д, йдслб Чего она може^ мнтерпрет1фов~тК'.
на других ЭВМ. Таким образом, компилятор на Р-код может
использоваться без каких-либо изменении для широкою клан .
ЭВМ, если для каждой из них написан свой интерпретатор
P-кода. Написание этого интерпретатора хотя и достаточно
сложно, но, конечно же, проще написания нового транслятора.
Такой подход может быть использован для переноса и друп
типов системного программного обеспечения без его переписи
вания. В качестве примера можно привести описанную в разд. т.
систему UCSD Pascal.
Устройство псевдомашины и соответствующего ей Р-код.'
часто вытекает из особенностей компилируемого языка. Напри
мер, псевдомашина для компилятора с Паскаля мО/йТТ иметь
такие команды, как вычисление индексов массива, в£оь1 и вы
ход из подпрограммы, элементарные операции над кЛДдаеств-
ми. Наличие таких емких команд упрощает процесс генбраци1
объектного кода, делаёт компилятор меньше и эффективнее
297
Кроме того, объектная программа на Р --------
намного короче, чем соответствующая Л"4' Часто отзывается
них кодах обычной ЭВМ. Это особенно cv.. P°rpaMMa “ «шин
с жестко ограниченным объемом операп,»^”™1""0 для «вшив
Очевидно, что выполнение нрогнамм Г 'У?’"'11-
интерпретации может оказатьсяР на₽мтого чм,'"Л' 8 Ре«»ме
„олнепие эквивалентных майн,иных X»? "ем
стенах это оказывается, однако, несуществен,, ,м"1\К,бгорых
пиляторы па Р-код были разработаны 1ля веппМ"°гие к0“-
однопользовательском режиме на henmuln “Пользования в
В этом случае время выполнения прогоаммм м,,кРоЭВМ.
не очень важным, если общая ироишодитеОказа1ься
ограничена временем, необходимым ,юл,,зоватевю Jj»
вания своих действий. •’«вателю для обдумы-
В тех случаях, когда время выполнения прогоаммч »
хотелось бы уменьшить, некоторые компиляторы Й Р к
аволяют использовать подпрограммы в машнн.Гых кЬют П
писав с р.кода в машинные кодь, небольшое 4nc^,a„fc;
часто используемых программ, как правило, можно достичь су-
щественного увеличения общей производительности. При этом,
конечно, приходится частично жертвовать легкостью переноса
программ на Р-коде. ' '
Наиболее широко известный компилятор на’Р-код^атб
UCSD Pascal компилятор, описанный в разд. 5Д 2- м 11
ПОНЯТИЯ ПСеВДОМЩЦППЬ| И P-Kgaa 32в^:;7ДТЦдько с этим ком-
ИаиЯ1'.Й xjStS дс-ле эти понятия являются более общи-
ми и используются в ряде других программных ’систем, напри-
мер в компиляторе на P-код, описанном в работе Норй [1981].
5.4;4. Компиляторы компиляторов
* ••
Написание компиляторов обычно связано с большими уси-
лиями и затратой большого количества времени. П^и созданн
некоторых его частей, особенно при разработке сканер р
пессора грамматического разбора, можно большую час
ты проделать автоматически. Компилятор KOVr,lL1^T^- < тк11
программное средство, используемое для (,ол914^11" Р11Вают ге.
компиляторов. Такого рода средства часто rai> ^пансля.
нёраторами компиляторов или системами п с р
’ Процесс использования типичного компилятора
ров иллюстрируется на рис. .5.28. Пользователь L . P()JP язы.
чик компилятора) предоставляет on"cW® р пексических Ира-
ка. йто оНйсание может состоять из наб р ‘ )Г0 языка,
вил, уцредедающих лексемы, и грамм ^пользуют эту пнфор-
Некоторые компиляторы компиляторов псп
ММгаММШИН
манию для генерации программ, осуществляющих сканирование
и грамматический разбор. Другие компиляторы компиляторов
создают таблицы, необходимые для работы стандартных про-
грамм осуществления лексического и синтаксического анализа,
поставляемых вместе с компилятором компиляторов.
В дополнение к описанию исходного языка пользователь
предоставляет также ряд семантических программ генерации
кода. Часто каждая семантическая программа соответствует не-
которому семантическому правилу грамматики, как это обсуж-
далось в разд. 5.1. Эти программы вызываются в процессе
Рис. 5.28. Автоматизация
лятора компиляторов.
создания компилятора при
использовании компи-
грамматическое. Рябова, как только распознана конструкция
гае к™Х™”™ COOT8eicTByroi»«; ВДВЙДОН Грайцатикн. Днг-
ГИС компиляторы компиляторов могут ОСУШССТВТЯтГ МРЖ IV ЛГ
^ТХЯМИ К ““«"Т^ским прог|?аммаГгГаматаческнйУпа
SS *рагментов исходной программы. ВI этом счу^е
ная *онмлР^'<Ь,Х пРедложеН|1Й вводится некоторая спешил
тнчесФкоРго naafi^’ НаП₽ИМер “ ВНДе ФР8™епта дерева грамма-
скнмТвогоаммам т, ™раЯ М0Жет бь,ть псре^на семаптиче-
низании лбтрг-г * ТаК°И подход обычно используется при опги-
предоставляют тя^° т К°Да' Компиляторы компиляторов часто
Данных и другую инфоСрмаштНЫе ЯЗЫК"’ Н0Тацию’ структуры
вана пои нап?ЛФ Рмацию> которая может быть испол ьзо-
Основипй й “ И семантических программ.
ляторов состоит ^ГпгШ ПрИ использ°вании компилятора комли-
ния компилятопя пРоцесса разработки и тестирова-
проделать полмлпя™НЗК° объем работы, который необходимо
систем в зависимлет еЛЮ’ сУщественно различается для разных
лю средств Сгрырг/ °Т гп$кости предоставляемых пользовате-
больше памяти и кп2пР°ВаННЫе компиляторы обычно требуют
компиляторы наХХИРУЮТ более медлвввыв программы, чем
чилятором объектный м, вручнУго- Однако генерируемый ком-
зовании компилятооа компы°ЖеТ оказаться лучше при нсполь*
Р пиляторов. В результате автоматизм*
пни разработки сканера пп«
использования некоторых ЕаММ грамматНЧескп^
«ыхдля написания «маитич«™“ь''ых 'Реасти пре?™ЗГ‘°ра "
=Xz=.s г;~ =S-==-
........ ~==1=г.=
f Краткое описание одного ич v ект"ого
(YACC) приведено в разд. 5.5.4. AaaSn?T°Pr Комп»лятоРов
меры компиляторов компиляторов ГХж°атеУЖДение и 'W
[1971] и Хопгуд [1959] н одержатся
Грис
в работах
5.5. Примеры реализации
I В этом разделе мы кратко опишем устройство
ляторов. В разд. 5.5.1 описывается компилятор ЕТН Р^с'н
(компилятор с Паскаля разработанный в Высшей политехи-
ЮУ601* школе в Цюрихе), который широко распространен m
машинах серии CYBER фирмы CDC. В разд. 5₽5 2 описыва
Ьгся компилятор UCSD Pascal (UCSD — University of Cali-
fornia San Diego)—один из лучших компиляторов на Р-код.
Оба эти компилятора являются однопросмотровыми и практи-
чески не осуществляют оптимизацию объектного кода.
В разд. 5.5.3 описан компилятор IBM FORTRAN Н, предна-
значенный для использования на машинах серии System/370
фирмы IBM. Это многопросмотровый компилятор, позволяющий
получить высокооптимизированный объектный код.
Разд. 5.5.4 содержит описание компилятора компиляторов
YACC, разработанного в Bell Laboratories для использования
в рамках операционной системы UNIX. Мы также кратко опи-
шем1 генератор сканеров LEX, обычно используемый вместе
с YACC
Так 'же как. и в наших предыдущих описаниях реальных
программных систем, мы не будем пытаться дать 1,он^р”
сания какого-либо из этих компиляторов. Для чита . •
лающих получить более подробную информацию, npi с.
обходимые ссылки.
5-5.1. Компилятор ЕТН Pascal”
бы! создан Никлаусом
Язык программирования ’’^^.сшей политехнической школе
Виртом во время его работы в В >
. " Исолишш.ы ма.срио.ш ... 'Jo1'"
?•*«•!. Пи, Language «"<1 it»
b,l,) Son», Перепечатано с разрешения»
(ЕТН) в Цюрихе в 1970 гг. Первый компилятор с Пас-
каля был написан в г- П°ЛУ'*енный опыт привел к пояз-
лению новой версии Паскаля в 1972 г. и разработке для нее
компилятора в 1972-1974 гг Этот компилятор используется в
настоящее время более чем в 150 организациях, расположенных
в разных частях света, и количество его пользователи неппе
рывно растет. Именно этот второй компилятор мы и опишем в
данном разделе. Более подробное описание содержится н ра
боте Амманн [1981]. Компилятор с Паскаля, разработанный в
ЕТН в Цюрихе (далее просто «компилятор ЕТН»), является
однопросмотровым компилятором, генерирующим коды тля
ЭВМ CDC 6000 и ЭВМ серин CYBER. Он является самокомпи-
лятором ') в том смысле, что сам он написан на том языке, ко-
торый компилирует. Одно из удобств такого подхода состоит в
.возможности переноса компилятора на новую машину. Исход-
ная версия компилятора, предназначенная для работы на ма-
шине А, модифицируется. су те*м, чтобы порождать объектный
код, предназначенный для машины В. Если эту версию компи-
лятора использовать для компиляции самого себя, то в резуль-
тате мы получим компилятор, предназначенный для работы на
машине В. Другое преимущество самокомпилятора состоит в
образовании обратной связи, улучшающей процедуры генерации
кода. Если компилятор будет модифицирован для получения
более эффективного объектного кода и далее будет использо
ван для компиляции самого себя, то в результате мы получим
более эффективный компилятор. Подобные самокомпиляторы
довольно широко используются. Так получилось, что два дру
гих описанных в разд. 5.5 компилятора также являются само-
компиляторами.
Компилятор ЕТН содержит лексический анализатор, подом-
ный описанному нами в предыдущих разделах. Этот анализа гщ
использует таблицу зарезервированных идентификаторов, р г
положенных в виде линейного списка в порядке увеличения и-,
длины, что облегчает идентификацию лексем. Синтаксический
анализ осуществляется на основе метода рекурсивного сну-'
Таблица имен компилятора организована в виде двои ! > >
дерева. Память, необходимая для таблицы имен п для -1!'
используемых структур данных, для более эффективного се
пользования выделяется динамически. После окончания ком
ляцни отдельной процедуры соответствующий ей фрагменту
лицы имен становится более ненужным. Следовательно, 1
освободить для дальнеиши
денную для него память можно
использования.
1 ’ В нашей литературе этот термин
о раскрутке или самораскру гке, — Прим.
редко употребляется, чаше ржi 1
персе.
Во время выполнения программы необходимая мя хране-
ния данных память выделяется динамически с неволь транш л
метода автоматического распределения памяти, oi:i;cainioi•> ц
разд. 5.3.1. Области инициализации порождают;.-.) и записав; -
ются в стек при вызове каждой процедуры. Эти области сг : -
пы между собой в цепочку в порядке их ноян it-иия в екке,
как это изображено на рис. 5.20. Существует также <п и ч.па-л
цепочка, содержащая только те области, переменные ипорых
доступны для использования в данный момент в соогвгтсттщ
с правилами видимости имен в Паскале. Эта нспоч;,.-: а т.п -
зуется для тех же целей, что и дисплеи, который мы , ;ц-
сматривали в разд. 5.3.4 (см. рис. 5.2G).
Чтобы улучшить генерируемый код. компилятор еле., н
содержимым всех 24 регистров ЭВМ серии С'. НЕ!? гл .ргмя
выполнения программы. Если в процессе генерации i
ется некоторый элемент данных, или указатель -.-i >)
адрес, то прежде всего п_рщщг-Тся содержимое этих рем'-
ЕСЛИ Значение или указатель уже шгю н-я
регистре, то не требуются никакие операции ре и.и. 1<«>г.:
необходимо загрузить на регистр X некоторый элемент ьъшмх.
компилятор ищет свободный регистр. Если в ппличин пи п
одного свободного регистра, компилятор выбирает тог г- гш гр.
значение которого должно быть заменено. Этот выбор основа :
на времени, которое прошло с момента последнею iicibtj1 юг;
ния содержимого регистра, а также на тине значенья. с..!<ло-
жащегося на регистре. Замена константы более пре.шочгчн-л i
на, чем замена значения переменной, поскольку коасчл:ь от
перезагрузить на регистр, когда это понадобится. И -паи юлы
метод выбора нужного регистра представляется весьма : /
тивным. Когда компилятор ЕТН был использован лл-.; ьыы
ляции самого себя, результирующий объектный >! бы
примерно на 30 % меньше кода, порожденною пре ю лив
версией компилятора, который не отслеживал сопржа•*.• р -
Тистров.
Компилятор ЕТН генерирует перемещаемый объектны:' и
в формате, совместимом с имеющимся в системе связывюшн)
загрузчиком. Все ссылки вперед внутри компилируй ни: вр<
недуры окончательно определяются до того, как к-т'.лшдяюр
писывает объектную программу на внешнюю память. Весь оот-
ектный код, соответствующий компилируем-)Й крошдхре.
хранится в оперативной памяти до тех пор, пока н.с а;
вёршена компиляция этой процедуры. Для этою .ишамвчес:
выделяется необходимая память. После заверю ним. ' '
компиляции процедуры соответствующий объев ;пып к»- - 1,111
сывается на внешнюю память и выделенная Для сг,. \|ь 'щгл
оперативная память освобождается.
302
5.5.2. Компилятор UCSD Pascal ""----—
Система UCSD Pascal представляет
с-тсму программирования, предназначений законченную си-
компыотеров и предоставляющую средства . ДЛЯ н^ьших
выполнения программ. Программы Рр1зпабо'1п? разРаботки и
этой системы, могут работать на большом?°™ННЬ,С 11 Рамках
различных марок. В этом разделе мм 1Количестве машин
UCSD Pascal. В разд. 6.5 содержится ™ "ШС^ компилятор
системы UCSD Pascal. Компилятор> UCsnXf С1У^ДенИевссЛ
ботан на основе компилятора на Р-кот -а ицл 1)азРа-
рихс, который в СВОК, очередь является Рм„ Т?""ого 11 Ц“‘
версией компилятора ЁТН. описанного в разд 55f“p5"a""''1
стцующее описание содержится в работе Нори' 119811 к??"'
.TJTC'p UCSD Pascal является однопросмотровым компиляторов
папи'Санпым Паскале, генерирующем P-код для псевдомаш» ’
мы (P-машины). ВхбДтТьГм и^ком компилятора является не-
сколько расширенный стандартный IlacKiak
P-машина для UCSD Pascal имеет стековую архитектуру и
поддерживает ряд структур данных и команд высокого уровн ;
Регистры общего назначения на Р-машинс отсутствуют. Д
большинства арифметических, логических и других операции
соответствующие аргументы находятся в стеке. Стек также и»
пользуется для запоминания параметров и справочной ннф-
мации о вызовах процедур и функций. Имеются несколько j
гистров специального назначения, которые используются опер:
ционной системой и интерпретатором P-кода. Например, таким
регистрами являются счетчик команд и указатель на те:
щую область инициализации.
Конструкция P-машины была разработана на основаниию
лиза объектного кода, получаемого при компиляции с Паска.
Была сделана попытка выделить наиболее часто встречают::
последовательности команд, которые занимают основное
•то в объектной программе, и предусмотреть необходимую
держку этих действий в P-коде. Одна инструкция P-кода м
обратиться к элементу данных, расположенному как в тек\ь
так и в любой другой области инициализации, связанно.! '
кущей процедурой. Отдельные инструкции P-кода п03В0ЛЯ1°с1|Вг-
числять индексы по массиву, выполнять операции над м ^ии,..
ми и строками, выполнять даже такие операции, как о i> • »»,
ние и пересечение множеств. Существуют также иН Р'цедур.
осуществляющие необходимые действия при вызове^ щ - К2К
Одна операция P-машины может вызывать такие деис TOpbix
образование области инициализации, модификация чТ„х
структур данных и операции поддержки соответствии
структур. Благодаря наличию таких специальных к ‘ 1еЯт'
ектная программа в P-коде обычно намного короче эк
303
ной объектной программы для машины с более тоалннмл
архитектурой. традиционной
Компилятор UCSD Pascal предоставляет поогпаммне™
можность непосредственно использовать командыP m?/03'
ри программы па Паскале. Эта возможность бывает
некоторых специальных случаях (например, при разоабАтг В
стемных программ нижнего уровня). Имеется также во™™*
ность генерации непосредственно машинного кода для затаи*
лого компьютера, используя дополнительный этап в поопес’^
компиляции. Генератор «местного кода» получает на входе чт
конченную программу на P-коде, сгенерированную компилято
ром, и транслирует заданные процедуры этой программы из
P-кода в объектный код заданного компьютера. Оттранслиро
ванная в машинные коды программа занимает больше памяти
чем соответствующий ей P-код; однако время работы оттранс-
лированных процедур может уменьшиться в 10 и более раз, по
сравнению со временем интерпретации Р-кода.
Более подробное описание компилятора UCSD Pascal и
P-машины можно найти в работах SofTech Microsystems
[1983] и Овергаард [1980].
5.5.3. Компилятор Fortran Н фирмы IBM
Компилятор Fortran Н был разработан для использования
на машинах фирмы IBM серий 360 и 370. Входным языком
компилятора является Фортран IV; на выходе компилятора фор-
мируется объектный модуль, который может быть обработан
редактором связей системы. Одна из основных целей, которая
ставилась при разработке этого компилятора,— получить эф-
фективный объектный код. Пользователь может выбрать один
из трех уровней оптимизации при каждом обращении к компи-
лятору.
Компилятор Fortran Н состоит из системного диспетчера,
управляющего процессом компиляции, четырех логических :,з
компиляции (обозначаемых как фазы 10, 15, 20 и 25) и Ф<>>(
обработки ошибок (фаза 30). Конкретные действия, с т;
вляемые на каждой фазе компиляции, и требуемое ч.. и?
зависят от выбранного уровня оптимизации. Компилятор п,
ставляет собой оверлейную программу, разбитую на i. ат
тов. Корневым сегментом оверлейной структуры является
стемный диспетчер. Все остальные сегменты представляй'
бой либо фазу целиком, либо логически завершенную час:ь
'<Т-
. J3
д-
. л-
сИ-
со-
кой-либо фазы.
Системный диспетчер осуществляет инициализацию *"'
лятора, вызывает различные фазы для выполнения и pv р
ляет необходимую для работы компилятора память. Он . '-ьже
принимает запросы на ввод-вывод, идущие из Д’.’нл ч>аз
I ’ St К<>МПИ.'!ЯТО|Ш
компи.жюра, и передаст их операционной системе для выпол-
нения.
Фаза 10 читает исходную программу и осуществляет лекси-
ческим анализ На эпш фазе заполняются необходимые инфоо-
мш/юиныс таблицы для всех переменных, констаил номепои
предложении, на.хо гящпхея в исходной программе. ’ Выхачлм
фазы 10 является последовательность пар оператор — оиепанл
г порядке их следования в исходной программе. В данном кон-
тексте термин оператор включает в себя такие элементы, как
скобки и запятые, в дополнение к обычным арифметическим
Логическим И родственным им операциям. Под термином опе-
ранд понимаются переменные, константы и литералы. Кроме
лексического анализа на фазе 10 осуществляются также печать
листинга исходной программы и печать таблицы ссылок, если
этого потребовал программист.
Фаза 15 разделена на 2 части. Первая часть транслирует в
последовательность четверок то, что получено на выходе фазы
10. Для анализа предложений исходной программы использу-
ется метод операторного предшествования. Если требуется
оптимизация объектного кода, на фазе 15 также осуществля-
ются разбиение программы на линейные участки и сбор инфор-
мации об операторах перехода и использовании констант и.
переменных в каждом участке. Вторая часть фазы 15 опреде-
ляет относительные адреса для хранения констант и их пере-
менных. Она тавд<е определяет адресные константы, необходи-
мые для адресации ••nix элементов данных.
Па фазе 20 реализуются различные методы оптимизации
объектного кода. Выполняемые действия зависят от уровня он-
чимпзашш, выбранного программистом. Если оптимизации во-
обще ие требуется, го на фазе 20 осуществляется выделение
регистров для операндов четверок. При этом, однако, не дела-
ется попытки максимально использовать все имеющиеся регист-
ры и не предпринимается попыток оставить значения операн лк
нт регистрах для дальнейшего использования. Эти действии на-
зываются иазобы.ч распределением регистров и осуществ ляю!: '
за один просмотр программы.
Если требуется первый уровень оптимизации, то на фазе д'
осуществляется полное распределение регистров. Его начаат. •
ине аналогично базовому распределению регистров, при
однако, более полно используются имеющиеся регистры и
лается попытка сохранить значения операндов на регистрах
последующего использования. Делается попытка также с*1 и
н ii> на регистрах в течение всего времени выполнения ои1’
ь-ш программы наиболее часто используемые операнды,
мог р а определенна регистров требует нескольких npocVi'"
bp ’ лея \ T(>4!£oii форй'ы представления программы. Па
‘-1. и<т|г'ся также оптимизация инструкций перехода.
° S’ Примеры рсализаци
305
10 на фа1С 20
адресами це.
бы избежать ненужной загрузки регистров
реходов. 1
Если задан высшиц уровень оптимизации
также осуществляется оптимизация циклов
деляется структура программы в терминах ВСего опРе‘
циклов я порядок, в котором эти "**
реализуются такие методы оптимизации как 5. Далее
подвыражений и удаление инвариантов цикта' 1V> ДеП"е ° 6 тих
не оптимизации па фазе 20 также осуществляется
описанное полное распределение регистров и оптимизация
реходов. llt’
В Па фазе 25 генерируется объектный код на основании ни-
вызы-
формации, порожденной предыдущими фазами Фаза 30
вается после окончания фазы 25, только если на пре\ытущих
фазах обнаружены какие-либо ошибки. Назначением этой фазы
является выдача соответствующих диагностических сообщений
Дальнейшая информация и компиляторе Fortran 11 со ten’
жится в IBM 119726]. 1
5.5.4. Компилятор компиляторов YACC
Компилятор компиляторов YACC (Yet Another Compiler-
Compiler—еще один компилятор компиляторов) является гене-
ратором программ грамматического разбора, который исполь-
зуется в рамках операционной системы UNIX. Этот компилятор
компиляторов использовался для разработки компиляторов с
языков Паскаль, Ratfor, АПЛ. Си и ряда других языков про-
граммирования. Он также использовался для менее традицион-
ных приложений, включающих, например, язык определения
типов и систему управления документами. В этом разделе мы
дадим краткое описание компилятора компиляторов Ъ\СС и
программы LEX — генератора программ лексического анализа,
связанного с YACC. Дальнейшая информация об этих про-
граммных средствах содержится в Джонсон [1980], Джонсон
[1975] II Леек [1975].
Компилятор компиляторов YACC используется вместе с со-
ответствующим лексическим сканером. Этот сканер вышш ‘‘
в процессе грамматического разбора каждый раз, к<л да т U -
ется очередная лексема. Сканер каждой лексеме с™в 1
ответствие целое число, определяющее тип эюп ,кмд- ’•
это было описано в разд. 5.1. Сканер также фор* 1)
цу имен обработанных идентификаторов. может
Подсистема LEX является генератором сканер.в- О«з
быть использована для порождения иренрамм tv Н
мото для YACC типа. Фрагмент спецификации.
вход системы LEX, изображен на рис. э \ юлжны
левого столбца представляет софой шаблон, с 4
сравниваться фрагменты входного потока
кончилось успешно, то вызывается прогммЛ сравнение за-
строки правого столбца. Эти программы нап^1ВеТСТВуЮЩеГ‘
программирования Си. Результатом работы ,,а языке
обычно является очередная распознанная пРогРамм
они заполняют необходимые таблицы и выполняют пп Ме того’
ные действия. л ,ягат дРУгие сход-
В примере на рис. 5.29а первому шаблону не соответ.™,„
ппкакие действия; его смысл состоит в том, чтобы уГал,иь
Jet
•»__ •*
U-zA-ZU Ca-zA-Z0-9J*
; /* игнорирование пробелов •/
return(LET);
return(MUL);
гeturn(ASSIGN)?
{занести в таблицу) return(ID)i
а
tftoken - ASSIGN TD LET MUL ...
statement : LET ID ASSIGN expr С ... J
expr 5 expr MUL expr £ $$ = build<HULr^lЛ3>;>
ехр г : ID £ ... 3
6
Рис. 5.29. Пример входных спецификаций для LEX и YACC.
пробелы из входного потока. Программы, соответствующие сле-
дующим трем шаблонам, должны сформировать на выходе тип
соответствующей лексемы: тип LET для ключевого слова let,
MUL для оператора * и ASSIGN для оператора =. Как уже
говорилось, внутренним представлением для LET, MUL и дру-
гих лексем являются целые числа. Пятый шаблон определяет
структуру распознаваемых идентификаторов. Первый символ
должен находиться в диапазонах а — z или А — Z. За ним мо-
жет следовать произвольное количество символов из диапазо-
нов а—z, А—Z или 0—9. Символ * в этом шаблоне указывает
на то, что допускается произвольное количество повторений
терма, предшествующего <». Программа этого шаблона должна
заполнить необходимые для описания найденного идентифика-
S 5. Примеры реализации
тмпалексемыС1[)ТВеТСТВУ10ЩИ^^^’‘‘^*_^Ф®Рмйровать~на_выхаде
р1,еВ5.2С9°аОТвВхеоХ“ИСТрСоОка '"^Фнкаииямн, при8еДениымй на
let х = y*z
будет представлена в качестве последовательности
LET ID ASSIGN ID MUL ID
лексем;
Обратите внимание, что выбирается именно первый совпавши»
шаблон, в результате чего ключевое слово Ге/ распознает?»
как лексема LET, а не как идентификатор ID. знается
LEX может использоваться для создания весьма сложных
сканеров. Однако для некоторых языков, таких как Фоптпан
лексические анализаторы все еще должны создаваться вруч-
В качестве входной информации генератор? процессоров
грамматического разбора системы YACC подается грамматика
языка, для которого создается компилятор, и набор требуемых
Деи81^э*!Ц, соответствующих правилам используемой грамматики.
Фрагмент Т5КИ.Х входных спецификаций представлен на
рис. 5.296. Первая Строка ТфеДстарляет собой описание типов
используемых лексем. Другие строк'й явл^ПбТСя правилами грам-
YACt вШЫЪает
матики. Грамматический процессор системы
связанную с каждым правилом семантическую программу, как
только распознана соответствующая конструкция языка. Каж-
дая такая программа может передать в другие программы не-
которое значение, присвоив его переменной $$'. Эти значения,
порожденные ранее проработавшими семантическими програм-
мами или сканером, хранятся в переменных $1, $2, и т. д. Они
определяют результаты работы программ, соответствующих
компонентам правой части правил грамматики, упорядоченных
слева направо.
Пример использования этих переменных приведен на
рис. 5.296. Семантическая программа, связанная с правилом
expr : expr MUL expr
строит фрагмент дерева грамматического разбора входного
предложения, используя порождающую функцию build. Постро-
енный фрагмент дерева присваивается на выходе из семантиче-
ской программы переменной $$. Аргументами порождающей
функции являются оператор MUL и значения (являющиеся
орагментами дерева грамматического разбора), порожденные
после распознавания операндов. Эти значения обозначены!*'! и
$.3
В некоторых случаях полезно вызывать семантические про1
граммы после распознавания каждого компонента грамматнче-
ского правила. Система YACC позволяет ЭТЛ
вызов семантических программ не только „ 0 Лслать> допуская
го правила, но и в середине анализа Vau °К°Пча,,ню кажд°-
такими программами, доступны всем' ост^Т, ’ п°Р°жденные
которые будут вызваны в процессе апализтп?' пР°гРаммам,
Пользователь может также определить глобальпые°пе„"рав"ла-
которые могут использоваться всеми семантически uTe,,’'uc’
мами и лексическим сканером. '"некими програм-
Порожденные системой YACC поонссеопм
разбора используют метод грамматического п? гатИЧеского
вверх, называемый LALR(l). Этот метод готется А? РЛ С""’у
класса наиболее интересных грамматик. В часгноети ®ольи,ог<>
ходимости избегать левой рекурсии. Возможно ктоХватю
даже неоднозначных грамматик, за счет введения ХолиитеТь
ных грамматических правил, устраняющих двусмысленность'
Порожденные YACC процессоры имеют очень хорошую снете
му обнаружения и диагностики ошибок. Она позволяет повтоо
но проанализировать фрагмент, в котором обнаружена ошибка
либо продолжить обработку входного потока, пропустив оши-
бочный фрагмент.
Упражнения
Раздел 5.1
1. Постройте по грамматике па рис. 5.2 дерево грамматического разбора
для следующих конструкций <id—list):
a) ALPHA
б) ALPHA,BETA,GAMMA
2. Постройте по грамматике па рис. 5.2 дерево грамматического разбора
для следующих конструкций <ехр):
a) ALPHA + ВЕТА
б) ALPHA - BETA*GAMMA
в) ALPHA DIV (BETA + GAMMA) - DELTA
3. Предположим, что правила 10 и 11 грамматики па рис. 5.2 измл
ны на
(схр) ::= (term) | (exp) * (term) | (exp) DIV (term)
(term) (factor) | (term) -ф (factor) | (term) — (factor)
Постройте деревья грамматического разбора для конструкций <ехр> "
в соответствии с такой модифицированной грамматикой. Каким образом
меления в грамматике повлияли па отношение предшествования для •' i'1 з
метических операторов?
4. Предположим, что правила 10 и И грамматики па рис. 5.2
пени на одно правило:
(схр) (factor) |(ехр) 4-(factor) |(ехр) —
— (factor) | (exp) * (factor) | (exp) DIV (factor)
Упражнения
309
Постройio деревья грамматического разбора для конструкций <ехр> упр. 2
ПО такой грамматике. Какие при этом возникают проблемы?
5. Модифицируйте грамматику на рис. 5.2 с тем, чтобы включить one-
....“ в форме XfY. Не забудьте о том, что возве-
...I приоритет, чем остальные
ранию возведения в степень
депие в степень должно
врмфме। ическис операции.
иметь более высокий
6. Модифицируйте грамматику на
ложення вида
IF условие THEN предложение —
где конструкция ELSE может быть
что условие имеет форму а < Ь, а >
рис. 5.2 с тем, чтобы включить пред-
1 ELSE предложение — 2
опущена. Вы можете предположить,
ь или в = 6. Здесь и и Ь —иденти-
фикаторы пли целые числа. Вы можете не заботиться
турах IF, т. е. предложение—1 и предложение — 2 —
ложениями.
о вложенных струк-
2 не могут быть 1F пред-
7. Модифицируйте грамматику иа рис. 5.2 так. чтобы список вывода
для оператора WRITE наряду с идентификаторами мог содержать заклю-
чённые в кавычки строки символов.
8. Составьте алгоритм, просматривающий входной ноток и распознаю-
щий идентификаторы и операторы. Идентификатор
до 10 символов. Он должен начинаться с буквы, а
если они есть, должны быть буквами или цифрами. Необходимо распо-
знавать следующие операторы: -f-, —, *, D1V и ; = . Ваш алгоритм должен
на выходе образовывать целое число, определяющее тип распознанной лек-
семы в соответствии с кодировкой, принятой на рис. 5.5. Если будет обна-
ружена недопустимая комбинация символов.
может иметь длину»
остальные символы,
вать число —1,
9. Модифицируйте написанный вами в
наряду с идентификаторами распознавал и
то алгоритм должен
упр. 8 сканер так,
целые числа. Целые
обрйзовы-
чиниться со знака (+ или
—), но не могут начинаться
10. Выберите какой-либо из знакомых вам языков
высокого уровня и напишите для него лексический сканер.
11. Осуществите грамматический разбор следующих
чтобы он
могут lid-
с цифры 0.
программирования
предложений
граммы на рис. 5.1, используя метод операторного предшествования и
рицу предшествования на рис. 5.7:
а) предложение присваивания в строке II;
б) описание в строке 3;
в) предложение FOR, начинающееся в строке 7.
при-
ма т-
5.1,
12. Осуществите грамматический разбор всей программы на рис.
используя метод операторного предшествования и матрицу предшесюованпя
на рис. 5.7.
13. Осуществите грамматически» разбор предложения присваивания и
строке 11 на рис. 5.1, используя метод рекурсивного спуска и процедуры,
нриведеииые на рис. 5.11.
14. Напйшите процедуры метода рекурсивного спуска, соответствующие
правилам для (dec—list}, (dec/ и (type> па рис. 5.9. Используйте эти про-
цедуры для разбора описаний в строке 3 па рис. 5.1.
15. Напишите процедуры метода рекурсивного спуска для других нетер-
миналов грамматики на рис. 5.9. Осуществите грамматический разбор всей
рис. 5.1 методом рекурсивного спуска.
16. ОДспользуйте программы на рис. 5.12—5.14 для генерации кода,
*>iветстуюшего следующим предложениям программы па рис, 5 1(
0) предложение присваивания и строке 11,
б) Предложение WRITE о строке 15;
Программы на
СО’
и) предложение FOR, начинающееся в строке 7.
Воспользуйтесь при этом деревом грамматического разбора in лиг В 4 п-и
определения порядка, в котором грамматический процессор паспочйяет пяч
личные конструкции, содержащиеся в этих предложениях опознает раз-
17. Используйте программы на рис. 5.12-5.14 для генерации кода всей
программы на рис. 5.1. н 1 ' кода всей
18. Напишите процедуры генерации объектного кода для новых ппяп
которые вы добавили к грамматике для определения предложений '1F. ’
19. Предположим, что грамматика на рис. 5.2 расширена путем ввете
ния переменных с плавающей точкой (<type> REAL) в дополнение к целым
переменным. Как при этом изменятся приведенные в тексте программы ге
нерации кода? Считайте, что допустимы смешанные арифметические вы
ражения, соответствующие обычным правилам Паскаля.
20. Приведенные в тексте программы генерации объектного кода ис-
пользуют непосредственную адресацию для обращения к целым константам
используемым в арифметических выражениях (например, число 100 в выра-
жении SUM DIV 100). Каким образом такие константы могут обрабатываться
компилятором для машины, не имеющей непосредственной адресации?
21. Какого типа ошибки в исходной программе могут быть обнаружены
во время лексического анализа?
22. Какого типа ошибки в исходной программе могут быть обнаружены
во время синтаксического анализа?
23. Какого типа ошибки в исходной программе могут быть обнаружены
во время генерации кода?
24. В чем таблица символов, используемая компилятором, может ог-
личатьоя от подобной таблицы ассемблера?
Раздел 5.2
1. Перепишите приведенные на рис. 5.12 и 5.13 программы генерации
объектного кода так, чтобы они порождали не объектный код, а четверки
2. Напишите программы генерации объектного кода из четверок, полу-
ченных программами упр. 1. (Наверное, вам для этого_понадобится про-
грамма, сходная по функциям с процедурой GETA на рис. 5.13.)
3. Воспользуйтесь программами из упр. 1 для получения четверок, со-
ответствующих следующему фрагменту программы:
READ(X,Y);
Z := 3 * X — 5 * V + X * Y;
4. Используйте программы из упр. 2 для получения объектною к1
из четверок, полученных в упр. 3.
5. Перепишите приведенные на рис. 5.14 программы генерации обы.<
кого кода так, чтобы они порождали не объектный кол, а четверки.
6. Используйте программы из упр. 1 и 5 для получения четверок,
ответствующих программе на рис. 5.1.
7. Разбейте полученные в упр. 6 четверки на линейные участки и
стройте блок-схему программы.
8. Предположим, что вы должны сгенерировать объектный код
УУМ/ДС из четверок, полученных н упр. 6. Предложите споеои р<п И
ления регистров для оптимизации объектного кода, которым бы iicuu
регистры S и Т для хранении значений переменных н промежуточны
эульгаюв.
Упражнения
Раздел 5.3
1. Составьте алгоритм работы пп
что область инициализации имеет преТ^Л "Р?ЦедУры „ ппр
2. Составьте алгоритм работы *"1Ы" "а рнс- 5-20РдХ°м°Же,”'и'
что область инициализации имеет nSe?™ про^ДУры в п? ₽ Т‘
3. Предложите способ использован^^тек""^ Р"С’ формат
и0СУн^=Г^
области свободной памяти? нению с использовавием”^"(“у1цества
4. Предположим, что массив описан езависнмо«
CMWRAT^MJ OF JNTEGE? ЛУЮЩ',М °6раз°«=
Сгенерируйте четверки для предложения
С(1] := О
5. Предположим, что массив описан следующим образом:
D: ARRAYf-10.. 10,2.. 12] OF INTEGER
Сгенерируйте четверки для предложения
D[I,J] :=* 0
6. Обобщите предложенные в разд. 5.3.2 методы для хранения трех-
мерных массивов по строкам. Для массива, описанного в виде
Е: ARRAYfl. .5,1.. 10,0. .8] OF INTEGER
сгенерируйте четверки для предложения: E[I, J, К]: — 0.
7. Как надо изменить базовый адрес массива А, определенный на
рис. 5.22а, чтобы избежать необходимости вычитать 1 из значения индекса
(четверка 1)? . г.
Я. Каких! ббриом- J де&ЦО обобщить на двумерные
массивы? w
9. Пусть массив Т описан как
Т : ARRAY[1. .5,1.. 100] OF INTEGER
Оттранслируйте следующие предложения в четверки и исключите общие
подвыражения.
К := J -
FOR I :=
BEGIN
T[I,J]
1;
1 TO 5 DO
:= К * K;
J + K;
:= K*K—1;
END
vnn 9 дтя исключения инвариантов
10. Модифицируйте четверки из упр. А-
НИКЛа. ИПГПЛРЯ при вызове
И. Составьте алгоритм поРоЖ^"“1
процедуры. Ваш алгоритм может • ис. адрес области инициализация,
плея (т. е. состояние до вызова ПР°^ДУР „уровень вложенности вызывав-
порожденной для вызываемой процедуры, и уи
мой процедуры.
Глава 6. Операционные системы
В этой главе будут рассмотрены функции операционных си-
стем и способы их разработки. Не пытаясь в единственной гла-
ве дать исчерпывающее изложение темы, явившейся предметом
многих книг, мы коснемся только наиболее важных идей и ре-
шений, иллюстрируя их примерами и снабжая ссылками па со-
ответствующую литературу.
Способы разработки операционных систем и их назначение
достаточно разнообразны. Одни, очень простые, предназначены
для обеспечения работы единственного пользователя на персо-
нальной ЭВМ. Другие, крайне сложные системы, дают возмож-
ность одновременной работы многих пользователей, управляют
высокоразвитыми аппаратными и программными средствами.
В разд. 6.1 рассмотрены основные свойства операционных си-
стем, которые присущи практически любому их элементу. Из-
за большого разнообразия операционных систем перечень этих
свойств необычайно сжат. Он состоит лишь из нескольких об-
щих функций, которые моГут быть взяты едва ли не как опре-
деления термина операционная система.
Раздел 6.2 содержит описание некоторых важных хвойстл
машинно-зависим ых-юпепанио»»1-^ СГГСТ“?.7,'а разд. 6.3 освещает
“Характеристики машинно-независимых реализаций. Многие из
рассматриваемых в этих разделах функций (к ним относятся,
например,- распределение системных ресурсов и управление
связью между различными пользователями) должны быть ре-
ализованы практически в любой операционной системе, поддер-
живающей одновременную работу многих пользователей.
В разд. 6.4 коротко излагаются некоторые альтернативны^
способы построения операционных систем. В разд. 6.5 описыва-
ются несколько реальных операционных систем, дающих пред
ставление лишь об отдельных формах и функциях подобном.1
программного обеспечения.
6.1. Основные функции операционных систем
Ниже вкратце рассматриваются основные функции, обычно
выполняемые всеми операционными системами. Главна>кзадач.|
операционной системы — упростить общение пользонЗТРлей с
6 1. Основные функции
--------------- операийоинму
ЭВМ'). Системное программна « ----------
стройкой вад базовыми авпа^а?нь!миеспечен,’е является на,
боту пользователя с машиил? I средствами и делает п?
печивая максимальную ппонЛп?0^ удобной Наприм^п 0(&*‘
система осуществляет Э-ВМ' ""Люш”,
= “ ресурсами,
Tio Сравнению с предыдущими главами приводимое нйже из-
пожёйиё основных свойств намного короче и иосит более об-
щий характер. Например, для ассемблеров, которые рассмотре-
ны в гл. 2, нам удалось найти общую структуру, не зависящую
of мйщинной реализации. Однако операционные системы для
пёрсональнбго компьютера в для суперЭВМ с большим числом
пользователей, за исключением основных подходов, буд) т силь-
но различаться.
Осндвные функции операционных систем могут быть изо-
бражены, как показано на рис. 6.1. Взаимодействие с про р .
мистами, операторами и т. д. осуществляется '‘еР систРемой.
пользователя, который поддерживается onepaui о
задачей операционной системы
Только с пользователем, но и с
обе<жЧиня, как транелят оры,
•> Не менее важной
удобйшо интерфейса нс
< и< темно, о про, рамМЦОГО
тори При ft. ped.
является создание
такими элементами
загрузчики, мони-
Именно его мы имеем в виду при ответе на вопрос: «Какого
характера операционная система?». Если интерфейс предусма-
тривает наличие некоторого языка управления, то, напримеп
запуск программы на счет может быть осуществлен пл ипм»..
де RUN Р. В разд. 6.1.1 приводится терминология, связанная с
операционными системами, и дается их классификация осно-
ванная на предоставляемом ими интерфейсе пользователя
В разд. 6.1.2 коротко описываются некоторые возможные функ-
ции интерфейса пользователя.
Для выполнения часто встречающихся задач операционные
системы предоставляют программам определенный набор услуг
Например, для чтения из файла некоторого набора данных
программа Р может использовать стандартную сервисную про-
грамму. Последняя вызывается командой типа readlj), с по-
мощью которой задается и имя файла. Всю заботу об осуще-
ствлении ввода-вывода, производимого на машинном уровне
возьмет на себя операционная система.
Сервисные программы могут рассматриваться как часть
операционного окружения задач, находящихся в решении.
О нем пойдет речь в разд. 6.1.3. Более подробно некоторые
сервисные функции и стандартные программы описаны в
разд. 6.2 и 6.3.
В данной главе предполагается, что функции операционной
системы реализованы только программным обеспечением. Од-
нако многие из них могут быть представлены программно-аппа-
ратными средствами (firmware), состоящими из набора микро-
программ. Дополнительную информацию об этом можно полу-
чить в Дейтел [1984].
6.1.1. Типы операционных Систем
Очень часто способы классификации
основываются на типе предоставляемого
операционных систем
ими интерфейса поль-
операционными систе-
зователя. Многие понятия, связанные с
мами, возникают из представления пользователей о сисз -
В данном разделе вводится терминология, наиболее часто •
пользуемая для описания операционных систем. При это'
всегда удается достичь полной ясности в определении г ь"
некоторых систем: они подпадают более чем под одну ка"
рию и их классификации в некоторых пунктах совпадаю^
Один из способов классификации связан с количсс
пользователей, одновременно обслуживаемых системой. <
вем однопрограммной систему, которая обеспечивает ра
одного пользователя. Это самый старый тип операционных
стем. Сейчас его можно встретить на микрокомпьютерах
сональных ЭВМ. Вероятно, и на гипотетической машине <
из-за малого объема памяти и нехватки каналов /что си1
315
ч;1тр\дняет обслуживание более одного пользой \
считать, что используется однопрограммная ги^? еля) слеДУет
Мультипрограммная система позволяет отноЛ
пять несколько заданий пользователей уппавл Р ННО ВЫ11°л-
„ределение.м процессора между ними. Для того ЭТОМ рас'
}1е мешали друг другу, операционная система соёёё ’ задання
соответствующее операционное окружение. Мультшгпои^ ”"Х
система схожа с мультипрограммной с той разницей, что ТпЛ*
bqh возможно использование более чем одного ЦП ’
Основная цель мультипрограммирования — увеличение ппо
изводительности вычислительной системы за счет разделения её
ресурсов между несколькими заданиями. Например, одно зада-
ние может занимать процессор, в то время как другое — о ки-
дать завершения операции ввода-вывода (подробнее об этом
см. в разд. 6.2).
Другой способ классификации операционных систем основан
на типе доступа, предоставляемого интерфейсом пользователя
В случае систем с пакетной обработкой в качестве задания вы-
ступает последовательность управляющих операторов, записан-
ная на машинных носителях (например, на перфокартах или
диске). За исключением смены дисков или лент, осуществляе-
мой операторами, всю заботу о считывании и выполнении зада-
ний берут на себя операционные системы. Порядок, в котором
выполняются задания, может быть выбран несколькими спосо-
бами. Вопросы планирования рассматриваются в разд. 6.3.
Диалоговый или интерактивный доступ некоторого числа поль-
зователей обеспечивается системами разделения времени. Опе-
рационная система исполняет директивы пользователей по мере
того, как они вводятся, стараясь дать ответ па каждую коман-
ду пользователя за разумно короткое время. Для обработки
внешних сигналов, поступающих, например, с различных дат-
чиков, и быстрого ответа на них используются системы реаль-
ного времени. К ним относятся операционные системы, paooia-
ющие на электронно-вычислительных машинах, управляющих
процессами, в которых время является критическим парамет-
ром (например, ядерная реакция пли полет космического ко-
рабля).
Вообще говоря, мультипрограммные системы пакетной оора
Ротки призваны сделать использование ЭВМ более эфф> v
ным. Основной задачей систем разделения времени ДОД/К
гатъся обеспечение хорошего времени ответа пользовате. я ;
Работающим в диалоговом режиме. Возможно, пр -
йется примириться с использованием машины <- м ёбеспечи-
Фективностъю. Системы реального времени должн\ для
Ват^ гарантированное время ответа на внешние с* довольно
*°’орых время является критическим паРд*,е |Стеме Напри-
часто все эти функции реализуются в одной
мер, многие системы пакетной обработки нередко поддерживав
ют интерактивный режим, а другие вдобавок осуществляют и
обслуживание процессов реального времени.
Дополнительные
стемах, равно как и
в Дейтел [1984].
сведения обо всех этих операционных си-
подробности об их создании, можно найти
6.1.2. Интерфейс пользователя
Интерфейс пользователя, предоставляемый операционной си-
стемой, предназначен для обеспечения нужд различных групи
людей, имеющих дело с ЭВМ. Например, для работы на пер-
сональной ЭВМ с простой операционной системой пользователю
предоставляется набор команд, посредством которых он может
подущать доступ к системным программам (трансляторам, ре-
дакторам,* загрузчикам), осуществлять, управление внешними
файлами. Подобный командный язык достаточно irpocr в ис-
пользовании; обычно имеется возможность в диалоге с маши-
ной получить подсказку или просмотреть меню, содержащее
варианты команд.
В более сложных системах может существовать несколько
различных языков общения с операционной системой. Непро-
фессиональным программистам предоставляется возможность ра-
ботать с ЭВМ на простом языке директив (command language).
Профессиональными программистами может применяться мощ-
ный и сложный язык, часто называемый языком управления
заданиями (job control language). Кроме того, обычно суще-
ствует специальный язык, при помощи которого осуществляется
взаимодействие операторов и ЭВ/М. Такой интерфейс оператора
позволяет запускать и останавливать задания, выяснять их со-
стояние'и состояние системных ресурсов, управлять внешними
действиями. Например, оператору может быть сообщено о не-
обходимости установить ленту или диск.
Разработка интерфейса пользователя обычно не влечет н
собой решения сложных технических задач, Между тем его со-
здание чрезвычайно важно, так как он эксплуатируется -
шинством’ пользователей. В идеале интерфейс пользователя и1'
жен быть разработан таким образом, чтобы отвечать трсо > j-
пням всевозможных типов пользователей и в то же вр- '
учитывать цели и задачи вычислительной системы. Допу
тельные сведения об интерфейсе пользователя можно нант
работах Дейтел [1984] и Питерсон [1983].
Для поддержки интерфейса пользователя операционная
стема должна иметь также стандартные сервисные прогрз' *
В случае персональной ЭВМ это могут быть программы
управления вводом с клавиатуры и выводом на дисплей-
более сложных системах — средства сопряжения с работаю1”-
6.1. Основные функции операцноппт систем
мн в режиме разделения времени удаленными теоминяпп
считывателями с перфокарт и печатающими устройв ми R
можно также наличие интерфейса между локалимлЛ Воз‘
и другими ЭВМ, объединенными в сеть Как част. сиегем°и
оператора многие операционные системы ведут вахппп1ерфеИСа
тистики активности системы; она может испольтоват
анализа производительности и обнаружения ошибок АЛЯ
6.1.3. Операционное окружение
Одной из наиболее важных функций операционной системы
является поддержка операционного окружения пользователь
ских задач. Оно состоит из ряда стандартных сервисных про
грамм, которые могут быть ^пользованы в процессе выполне
ния задачи и лредоставдоь ^едстиз Мя ^правлёи'Гя
ми ёЬ.щН£ДИтеже!, системы, выделяя их пользователю по мере
надобности.
В качестве примера услуг, предоставляемых операционным
окружением, рассмотрим функцию ввода-вывода. Почти все
операционные системы имеют стандартные программы, помо-
гающие в осуществлении таких операций. Предположим, что
программа работает на УУМ под управлением однопрограмм-
ной системы. Чтобы прочитать байт без помощи операционной
системы, программа должна содержать цикл, в котором анали-
зируется состояние устройства и выполняется команда "RD (см.
рис. 2.1). Обнаружение и исправление ошибок также возложено
на саму программу.
Наличие поддержки со стороны операционной системы силь-
но облегчает задачу. Программа пользователя может просто
инициализировать стандартную сервисную программу, задав
устройство, которое должно быть использовано. За всеми нюан-
сами, такими как опрос состояния и подсчет переданных бай-
тов, проследит операционная система. Она же примет необхо-
димые меры по исправлению ошибок.
Стандартная сервисная программа, подобная описаний:
выше, может восприниматься как расширение базовой машины.
Типичная операционная система содержит много подобных уру
грамм. Вместе взятые, они составляют РосшиРе“"У'°*“
которая и используется во время выполнения пр’ р р аоатнух
граммам не нужно опускаться до УР0ВНЯ поедост₽авлЯет
средств, поскольку все функции и а Р Ч€М реаль-
Расширенная машина. Она проще в исп ..о.- - > операций
»**. Это касается, например, нюанХЛа Например, опера-
нда-вывода. Есть и другие преимущества. подвержены
"ии ввода-вывода на расширенной к рбнаруЖенлем и неправ.
Гибкам, чем на реальной, та\какя Система
ЛеНв$м ошибок следит операционна
Иногда расширенную машину называют виртуальной. Одна-
ко термин «виртуальная машина» может иметь и другой смысл
Это двоякое использование термина описывается в разд 6 4
Операционное окружение мультипрограммных операционных
систем содержит также программы, которые управляют ресур
сами ЭВМ, выделяя их по необходимости заданиям пользова-
телей. Например, оперативная память распределяется’между
заданиями, одновременно находящимися в решении, централь
ный процессор предоставляется заданиям согласно заранее вы-
бранной стратегии. За исключением конкретных запросов опе-
рационной системе заданиям пользователя нет необходимости
иметь дело с управлением ресурсами. Благодаря операционно-
му окружению каждое задание выполняется как бы на отдели
ной расширенной машине, *отя в действительности базовая
мапТТГСТЗ бьГгь распределила уёжду несколькими пользо-
вателями.
В некоторых системах программы пользователей Могут вызы-
вать функции операционной системы, обращаясь непосредствен
но к фиксированным областям памяти. В документации по опе-
рационной системе для пользователя дается описание областей,
предназначенных для данных, и входных точек вместе с их
реальными адресами. Например, точка входа стандартной сер-
висной программы ввода-вывода может находиться в нами i n
по адресу 238. После установки в регистрах требуемых пар
метров программа пользователя может инициализировать эту
сервисную функцию командой JSUB 238. Иногда возможно
наличие в памяти одной точки входа для всех сервисных про-
грамм, нужный тип обслуживания может быть определен при
помощи кода запроса.
Способ запроса связи с операционной системой при помош::
обращения к фиксированной области памяти используется
микрокомпьютерах и персональных ЭВМ. Однако этот мепн
часто не удобен и является источником ошибок; кроме того, < ।
может предоставить пользователю возможность обойти ср<
ства защиты, встроенные в операционную систему. В
развитых системах пользователи запрашивают функции опера
ционных систем в основном при помощи специальных мани1
пых команд, таких как вызов супервизора (SVC —Super
Call). Выполнение команды SVC вызывает прерывание, вJ
зультате которого управление передается сервисной ста,
ной программе операционной системы. Код, которым сопрс»
дается команда SVC, определяет тип запроса. Обработка
рываний операционной системой рассматривается в разд
Как правило, в машине любое прерывание вызывает пеР^|Ме
ЦП из режима пользователя в режим супервизора. В Ре''\тв3
супервизора могут быть использованы все команды и сРеДСтоМ
машины. Многие части операционной системы работают в
6.2. Машинно-зависимые свойства операционных СНСтем
1 -- . W 1 <J
режиме. При этом в режиме пользователя недопустимо выппп
некие некоторых команд. К таким командам могут от?юситкЛ'
например, функции ввода-вывода, установка флагов защиты S
переключение ЦП из одного режима в другой. Примеры таких
команд будут рассмотрены ниже. Ограничения, накладываемые
на использование привилегированных команд, заставляют п
грамму пользователя обращаться к услугам операцией ого
окружения. Таким образом, вместо непосредственного испол ™
вания функций базового аппаратного обеспечения программы
должны иметь дело с интерфейсом расширенной машины Огги
ничения также не дают программам пользователей вмешиваться
случайно или намеренно в функции управления ресурсами осу-
ществляемые операционной системой. Привилегированные
команды, равно как и режим пользователя/супервизора (или
эквивалентный ему), необходимы практически для всех систем
поддерживающих одновременную работу более чем одного поль-
зователя.
В разд. 6.2 и 6.3 рассматриваются разнообразные функции
и услуги, обычно предоставляемые операционным окружением.
На этом уровне между операционными системами, которые мо-
гут оказаться совершенно различными в интерфейсе пользова-
теля, есть много общего. Многие рассматриваемые технические
приемы могут быть использованы с некоторыми изменениями
почти во всех операционных системах: пакетной обработки, раз-
деления времени, реального времени и т. п.
6.2. Машинно-зависимые свойства
операционных систем
Одной из наиболее важных функций операционной системы
является управление ресурсами ЭВМ, на которой она работает.
Многие ресурсы имеют непосредственное отношение к аппарат-
ным устройствам, таким как центральная оперативная память
каналы ввода-вывода и ЦП. Таким образом, многие фу '
операционной системы тесно связаны с архитектурой май >.
Рассмотрим, например, машину УУМ. У нее м ппепыва-
Ративная память, отсутствуют каналы ввод^‘вь1^ ;наРмРОжет
ния, нет команд вызова супервизора Так ма, смысла
быть удобна в качестве персональнойЭВ , Таким об-
работать одновременно нескольким ртп^^ЯмашиНь1 УУМ
Разом, операционная система для стандартной с
бУДет однопользовательской с ПР°СТЬ‘ d)VP кций операционного
|,0«’1ьзователем и минимальным набор . ФУ простые возмож-
°к1>Уження. И если она предоставит как рассматривались
"бсти, то их вряд ли будет больше тех, что Р
h Разд. 6.1.
ЭВМ УУМ/ДС, наоборот, имеет гораздо большую оператив-
ную намять, каналы ввода-вывода и обладает многими другими
свойствами, отсутствующими у стандартной машины УУМ. На
УУМ/ДС хорошо иметь мультипрограммную операционную си-
стему. Она позволит распределять между несколькими одно-
временно работающими пользователями доступные им ресурсы
расширенной машины, а также лучше использовать усовершен-
ствованные программные средства. Конечно, разделение вычис-
лительной системы между несколькими пользователями создает
много проблем, подобных распределению ресурсов. Все они
должны быть решены операционной системой. В дополнение к
этому операционная система должна осуществлять поддержку
более развитых функций аппаратуры, таких как прерывания и
ка н а л ьн ы й в во д-в ы вод.
В данном разделе мы рассмотрим некоторые функции ма-
шинно-зависимых частей операционных систем. Для этого бу-
дет использована терминология ЭВМ УУМ/ДС; однако неко-
торые принципы могут быть легко перенесены на другие маши
пы, у которых архитектурные особенности схожи с УУМ/ДС.
Мы обсудим в ходе изложения ряд важных свойств аппарат-
ных средств УУМ/ДС. Для упрощения ссылок все эти свой
едва резюмированы в приложении В.
Раздел 6.2.1 знакомит читателя с основными принципами
прерываний и их обработки, используемыми на всем протяже-
нии остальной части главы. В разд. 6.2.2 обсуждаются вопросы,
связанные с распределением ЦП между несколькими заданиями
пользователей, работающими в мультипрограммном режиме
В разд. 6.2.4 и 6.2.5 обсуждаются вопросы разделения ц. иг
ральной памяти между несколькими пользовательскими з: 11-
пнями. В разд. 6.2.4 дается представление о средствах упрлн-
ления реальной памятью, а в разд. 6.2.5 — о важном поил е -
виртуальной памяти.
6.2.1. Обработка прерываний
Прерывание (interrupt)—это сигнал, заставляют.!' 1
менять обычный порядок исполнения потока команд. Во: 1
новение подобных сигналов обусловлено такими событиями.
завершение операций ввода-вывода, истечение заранее
ного интервала времени или попытка деления на нуль.
Рис. 6.2 дает представление о последовательности собе
происходящих в ответ на прерывание. Предположим, что а {
мент поступления от некоторого источника сигнала преры’
программа Л находится в решении. В результате управi'
автоматически передается на блок обработки прерываний^
блок ОП, а также обработчик прерываний), который оо '
является частью операционной системы. Этот блок предн 1''
— Машинно-зависимые свойства операционно систем
чей для выполнения некоторых действий п
вызвавшее прерывание. После завершения "а условис.
вне может быть снова передано в tv тп!.Я бр 6 КИ УпРавле-
ее выполнение было прервано У У пРогРаммь1 А, где
...В- ТОЛЬКО что описанной последовательное™ событий воз-
быть совершенно не
никновение и обработка прерывания могут
. Программа А
Рис. 6.2. Основная концепция обработки прерываний.
связаны с программой А. Например, оно может быть вызвано
завершением операции ввода-вывода, выданной другой про-
граммой. В общем случае невозможно предсказать,
какой причине программа А будет прерва-
на. Другими словами, по отношению к ней
прерывания возникают асинхронно. За со-
хранением текущего состояния машины во
время прерывания программы А, а также
за его восстановлением, когда А будет про-
должена, следят аппаратные и програм-
мные средства. Благодаря этому в случае
прерывания ничто, за исключением вре-
Класс
II
in
IV
Рис.
когда и по
Тип
прерывания
svc
Программное
По таймеру
Ввода/вывода
6.3. Типы прг-
рываннй в
УУМ/ДС.
деле для Л даже
мени, не влияет на ее выполнение. На самом
не существует способа узнать, имело место прерывание ил
II ст
На рис. 6.3 приведены четыре класса прерываний для ЭВМ
УУМ/ДС. SVC-прерывание (класс I) возникает при
нии ЦП команды вызова супервизора. Эта команда исп >. -
ется программами для вызова функции операционнойi с? ’
Программное прерывание (класс II) возникает при о[]Ь|Т.
некоторой ситуации, такой как деление на нуль, ил Розм0ЖП0
ке выполнить неправильную машинную команду ,
И Jah. 792
Центральная л а мять
• •
• • • •
Too Новый SW
103 Новый PC
Рабочая 106 Старый SW
область SVC-npe-’ рывэний 109 Старый PC
юс Область сохранения
регистров
130 Новый SW
Рабочая область 133 Новый PC
136 Старый SW
программ- 139 Старый PC
ных прерыва- ний J3C Область сохранения регистров
%;
Регистры
SW
PC
Рабочая
область
прерывания
ло таймеру
Рабочая
область
прерывания
ло вводу-
выводу
р 160 Новый SW
163 Новый PC
166 Старый SW
169 Старый PC
16С Область сохранения регистров
190 Новый SW
193 Новый PC
196 Старый SW
199 Старый PC
19С Область сохранения регистров
• • • •
а
Рис. 6.4. Операции контекстного переключения, вызванные а — прорыв
по таймеру и б —командой LPS 166.
Рабочая
область
SVC-пре-
рываний
Рабочая
область
программ-*
них пре-
рываний
Рабочая I
область J
прерывания"
по таймеру
Центральная память
• • •
100 Новый SW
103 Новый PC
106 Старый SW
109 Старый PC
юс Область
сохранения регистров
130 Новый SW
133 Новый PC
136 Старый SW
139 Старый PC
13С Область сохранения регистров
160 Новый SW
163 Новый PC
166 Старый SW
169 Старый PC
16С Область
Регистры
SW
PC
А
L
S
т
323
190
193
сохранения
регистров
Рабочая I
область
прерывания 4
ло вводу-
выводу
Рис. в,4, Продолжение.
И*
196
199
19С
Новый SW I
Новый PC
Старый SW
Старый PC
Область
сохранения
регистров
в процессе работы программы. Приложение В содержит пол-
ный перечень условий, которые могут вызвать программное
прерывание. 1 1
Прерывание по таймеру (класс III) вызывается интерваль-
ным таймером ЦП. Этот таймер содержит регистр которому
может быть присвоено определенное начальное значение гю
средством привилегированной команды STI. Значение этого
регистра автоматически уменьшается на 1 после использова-
ния каждой миллисекунды времени ЦП. Когда это значение
становится равным нулю, происходит прерывание по таймеру
Подобный интервальный таймер используется операционной си-
стемой для определения времени, в течение которого программа
пользователя может оставаться под управлением машины
Прерывание по вводу-выводу (класс IV) вызывается кана-
лами или устройствами ввода-вывода. Причиной многих таких
прерываний является нормальное завершение некоторой опера-
ции ввода-вывода; однако они могут также оповещать о воз-
никновении различных ошибочных ситуаций.
Когда происходит прерывание, состояние ЦП сохраняется, а
управление передается стандартной программе обработки пре-
рываний. В заключении рассмотрим метод для УУМ/ДС.
Как показано на рис. 6.4, в машине УУМ/ДС для каждого
класса прерываний имеется соответствующая ему рабочая об-
ласть прерываний. Например, область, соответствующая преры-
ванию по таймеру, начинается с адреса памяти 160. Когда про-
исходит прерывание по таймеру, содержимое всех регистров
сохраняется в этой области (см. рис. 6.4а). Затем из двух пер-
вых слов области заранее занесенные туда значения загружа-
ются в слово состояния SW и счетчик команд PC. Загрузка и
сохранение регистров осуществляются аппаратными средствами
машины автоматически.
Загрузка счетчика команд новым значением адреса автома-
тически вызывает передачу управления на соответствующую
команду. Этот адрес, заранее сохраненный в рабочей области
прерывания, представляет собой начальный адрес стандарт ы
программы обработки прерываний по таймеру. Загрузка с.ю: i
SW также вызывает определенные изменения в состоянии ИН-
После выполнения в ответ на запрос на прерывание любою1
требуемого действия стандартная программа обработки преры
ваний выполняет команду загрузки состояния процессор!
(LPS — Load Processor Status), в результате чего управление
передается прерванной программе (см. рис. 6.46). Команд1
LPS вызывает загрузку сохраненного содержимого SW. 1 '
и других регистров из соответствующих слов области сохоанд
ния, начиная с адреса, указанного в команде. Это приводи!
восстановлению содержимого регистров и состояния ЦП,
рые были в момент прерывания. Управление затем передаст'1
на команду, перед выполнением которой произошло прерывание-
Сохранение и восстановление состояния ЦП и содержимого ш-
гистров часто называют операцией контекстного переключения
Слово состояния SW содержит часть информации потопая
^ywHAvM/n6rPaKOTKM ПрерЬ,ВъН™ Мы ГОВОР™ 0 содержимом
SW в УУМ/ДС. Большинство ЭВМ имеет аналогичный регистр
часто называемый словом состояния программы или словом
состояния процессора.
Разряды Имя поля
0 MODE
1 IDLE
2-5 ID
6-7 СС
8-11 MASK
12-15
16-23 ICODE
_______Использование
О»режим пользователя, 1 = режим супервизора
О=активен. 1= пассивен
Идентификатор процесса
Код условия
Маска прерываний
Не используется
Код прерываний
Рис. 6.5. Содержимое слова состояния УУМ/ДС.
На рис. 6.5 показано содержимое SW. Первым битом (MODE)
задается режим, в котором находится ЦП — пользовательский
или супервизора.
Обычные программы выполняются в пользовательском ре-
жиме (MODE = 0). Когда происходит прерывание, новое за-
гружаемое содержимое SW имеет MODE = 1, что автоматиче-
ски переводит ЦП в режим супервизора, тем самым становится
возможным использование привилегированных команд. Перед
тем как значение SW будет сохранено, в поле ICODE авто-
матически устанавливается значение, указывающее на причину
прерывания. В случае SVC-прсрываний ICODE присваивается
значение, заданное пользователем командой SVC. Он опреде-
ляет тип сервисного запроса. При программном прерывании в
ICODE отражен тип вызвавшего его условия, например деление
на нуль. При прерывании по вводу-выводу в ICODE дан номер
канала, породивший прерывание. Дальнейшую информацию о
возможных значениях ICODE можно найти в приложении В.
В SW содержится также код состояния СС. Сохранение
SW автоматически спасает значение кода состояния прерванно-
го процесса. Об использовании полей IDLE и ID будет расска-
зано ниже в этой главе. Поле IDLE определяет, выполняет ли
ЦП команды или простаивает. В ID содержится 4-битовое зна-
чение, идентифицирующее текущую выполняемую программу.
Оставшееся поле слова состояния (MASK) используется
для контроля за разрешением прерываний. Это требуется для
того, чтобы избежать потери сохраненной ранее информ
о состоянии процесса. Предположим, например, что произо!.
прерывание по вводу-выводу. Значения SW, IC и других 1
гистров будут сохранены в рабочей области прерывания ввода-
вывода, о которой только что было рассказано, а ЦП начнет
выполнение обработчика прерываний по вводу-выводу. Если до
конца обработки первого прерывания произойдет еще одно,
снова будет иметь место контекстное переключение. Однако на
этот раз в качестве содержимого регистров, сохраняемого в ра-
бочей области, окажутся значения, используемые обработчиком
прерываний. Значения же, сохраненные при первом прерывании,
будут утрачены, поэтому вернуть управление программе поль-
зователя, которая в тот момент выполнялась, будет нельзя.
Чтобы избежать этого, нужно не допустить наступления пре-
рываний определенного типа, пока первое из них не будет об-
работано. Это достигается использованием поля MASK слова
состояния. В MASK каждый бит соответствует некоторому
классу прерываний. Если какой-то бит установлен в 1, то пре-
рывания соответствующего класса разрешены, если в 0, то за-
прещены. В последнем случае говорят, что они маскированы.
(часто их также называют запрещенными или закрытыми).
Однако маскированные прерывания не теряются, потому что
сигнал, вызвавший прерывание, сохраняется аппаратурой. Вре-
менно задержанное таким способом прерывание называется от-
ложенным. Когда, вследствие того что MASK сброшена, преры-
вания соответствующего класса вновь разрешаются, сигнал опо-
знается и происходит прерывание.
В УУМ/ДС маскирование прерываний находится под конт-
ролем операционной системы и зависит от значения MASK в
SW, которое заранее сохраняется в рабочей области каждого
прерывания. Можно запретить все прерывания, установив все
биты MASK в 0. Однако в действительности поступать подоб-
ным образом нет необходимости.
Каждому классу прерываний на УУМ/ДС присвоен опреде-
ленный приоритет прерываний. Наивысший приоритет имеют
SVC-прерывания (Класс I), затем идут программные (Класс II)
и т. д.1). Поле MASK в слове состояния устанавливается в со-
ответствии с классом прерывания так, чтобы все прерывания с
равным или более низким приоритетом были запрещены, а с
более высоким разрешены. Например, слово состояния, загру-
женное в результате программного прерывания, будет иметь
биты MASK, соответствующие прерываниям — программным, по
таймеру и по вводу-выводу, установленными в 0; эти классы
прерываний будут запрещены. Бит в MASK для SVC-прерыва-
ний будет установлен в 1, поэтому они будут разрешены. Ко-
гда прерывания по завершении работы обработчика прерывании
открываются, среди ожидающих может оказаться более одной'
*’ Нс во всех операционных системах приоритеты распределены *;|К»
как предлагает автор. — Прим. ред.
класса прерываний (например, по таймеру и по вводу-выводу).
В этом случае первым опознается то, что имеет более высокий
приоритет.
Рели используется такая система приоритетов, то програм-
ма обработки прерываний сама может быть прервана. Каким
образом происходит вложенное прерывание, показано па
рис 6 6 По прерыванию по вводу-выводу состояние програм-
мы Л выполняющейся в этот момент на ЦП, сохраняется, а
управление передается обработчику прерываний по вводу-выво-
ду Во время его работы происходит новое прерывание — уже
по таймеру, в результате чего управление передается обработ-
чику прерываний по таймеру. По завершении обработки этого
прерывания при помощи команды LPS из рабочей области
прерывания по таймеру восстанавливается состояние ЦП. В ре-
зультате управление снова передается обработчику прерываний
по вводу-выводу. Так как опять загружено старое значение
MASK, прерывания по таймеру, которые были запрещены, сно-
ва открываются. Однако прерывания по вводу-выводу по-преж-
нему остаются закрытыми. После завершения обработки пре-
рывания при помощи уже другой LPS восстанавливается
состояние ЦП, которое было в момент первого прерывания. Те-
перь все прерывания открыты, потому что в слове состояния,
используемом программой А, все биты MASK установлены в I.
Ниже мы увидим, как прерывания могут быть использованы
при реализации таких функций операционной системы, как
планирование процессов, управление вводом-выводом и распре-
деление памяти. -'
6 2.2. Планирование процессов
Процессом (process), или заданием (task), часто называет-
ся программа, находящаяся в решении. Другие возможные опре-
деления процесса можно найти в Дейтел [1984]. Для выполне-
ния вычислительной работы операционная система выделяет
процессам ЦП. В однопрограммной операционной системе при-
сутствует только один пользовательский процесс. Однако в
мультипрограммной системе на ресурсы может претендовать
много независимых процессов. Планирование процессов — это
управление распределением ресурсов ЦП между различными
конкурирующими процессами путем передачи им управления
согласно некоторой стратегии планирования.
Во многих случаях процесс соответствует заданию пользова-
теля. Однако некоторые операционные системы позволяют од-
ному заданию создавать несколько различных процессов, вы-
полняемых одновременно. Вдобавок некоторые системы разре-
шают одной программе быть разделенной между несколькими
независимыми процессами. Дальнейшую информацию по этому
вопросу можно найти в Дейтел [1984]. Здесь мы будем счи-
тать, что каждому процессу соответствуют только одна про-
грамма и одно задание пользователя.
Процесс создается, когда выполнение задания пользователя
начинается, и уничтожается, когда задание завершается. Во
время своего существования процесс может находиться в трех
состояниях. Процесс активен (running), когда оп использует
ЦП для выполнения своих команд. Процесс блокирован,
(blocked), если его выполнение может быть продолжено только
после наступления некоторого ожидаемого им события. Напри-
мер, процесс может быть блокирован, потому что ему требует-
ся ждать завершения операции ввода-вывода. Процессы, кото-
рые не блокированы и не активны, называются находящимися
в состоянии готовности (ready). Этим процессам будет переда-
но управление после того, как текущий активный процесс его
отдаст.
На рис. 6.7 показаны возможные переходы из одного со-
стояния в другое. В любой момент времени активным (т. с.
использующим ЦП) может быть только один процесс. При пе-
редаче управления процессу пользователя операционная систе-
ма устанавливает интервальный таймер. Тем самым задается
квант времени, являющийся максимальным количеством време-
ни ЦП, на которое процесс получает управление. Если это вре-
мя истекает, процесс переводится из состояния активности в со-
стояние готовности. После этого операционная система, согласно
стратегии планирования, выбирает следующий процесс, пах»
дящийся в готовности, переводит его в состояние активности
и передает ему управление. Выбор процесса и передачу па него
управления часто называют диспетчеризацией. Часть опсрацц-
онной системы, выполняющая эту функцию, называется диспет-
чером (dispatcher).
Может оказаться, что активный процесс, не использовав пол-
ностью предоставленного ему кванта времени, будет ожидать
наступления некоторого события, например завершения опера-
ции ввода-вывода. В этом случае активный процесс блокирует-
ся, а какой-то новый процесс активизируется. Когда же ожидае-
мое событие наступает, соответствующий заблокированный про-
цесс переводится в состояние готовности и может снова стать
Событие
наступило
Рис. 6.7. Изменение состояний процесса.
кандидатом на обслуживание. Операции ожидания события и
оповещения о том, что событие наступило, реализуются при по-
мощи сервисных запросов операционной системе (с использова-
нием SVC) '), Механизм, чаще всего применяемый для уста-
новления соответствия между процессами и ожидаемыми ими
событиями, рассматривается ниже в данном разделе.
Обычно до своего завершения процесс много раз пребывает
в состоянии активности, готовности и блокировки. Для того
чтобы это никак не повлияло на результаты вычислений, каж-
дый раз, когда процесс теряет активность, его текущее состоя-
ние должно быть сохранено. Когда же процесс снова будет ак-
тивизирован, это состояние должно быть восстановлено. Ин-
формация о состоянии каждого процесса хранится операцион-
ной системой в блоке состояния процесса (PSB — Process Sta-
tus Block). Блок состояния процесса создается, когда процесс
входит в решение, и уничтожается, когда процесс завершается.
Блок PSB содержит информацию о том, в каком состоянии
процесс находился (активности, готовности или блокировки).
В нем имеется область, используемая для сохранения машин-
ных регистров (включая SW и PC) и другой всевозможной
информации (например, о системных ресурсах, используемых
процессом).
*> Не обязательно с помощью SVC, но н по прерываниям! — Прим, ред.
Общий вид алгоритма, используемого при диспетчеризации,
показан на рис. 6.8. При передаче управления от одного про-
цесса другому прежде всего необходимо сохранить информацию
о состоянии активного процесса. Если процесс был заблокиро-
ван, так как он использовал весь свой квант времени, то
информация о состоянии может быть найдена в рабочей обла-
сти прерывания по таймеру. Если процесс отдал управление
(выполнив SVC-запрос), потому что ему требуется дождаться
наступления некоторого события, информация о состоянии бу-
дет храниться в рабочей области SVC-прсрываний. Конечно,
procedure DISPATCH
обновить PSD Активного процесса (если он есть)
выбрать следующий Готовый процесс для передачи ему управления
if готовый процесс найден then
begin
пометить выбранный процесс как Активный
выделить квант времени, установив командой
STI интервальный таймер
командой LFS передать управление выбранному процессу
end
else
командой LPS перевести ЦП в состояние простоя
Рис. 6.8. Алгоритм диспетчеризации.
может оказаться, что активных процессов пет. Это может слу-
читься, например, если все процессы в системе находятся в
заблокированном состоянии. Тогда информацию о состоянии
сохранять не надо.
После сохранения состояния предыдущего активного процес-
са диспетчер выбирает для активизации новый процесс. Чтобы
задать квант времени, выделяемый выбранному процессу, дис-
петчер устанавливает интервальный таймер, затем, используя
команду LPS для загрузки информации о состоянии, хранимой
в PSB данного процесса, осуществляет передачу управления.
Если процесса, находящегося в состоянии готовности, нет, то
диспетчер для перевода ЦП в состояние простоя (idle), исполь-
зует LPS, загружая слово состояния с IDLE = 1 (рис. 6.5).
Выбор следующего процесса для диспетчеризации осущест-
вляется несколькими способами. В первом из них, называемом
круговым (robin round), все процессы считаются равноцен-
ными. Диспетчер циклически просматривает все PSB, выбирая
следующий процесс из тех, что находятся в состоянии готов-
ности. Каждому активизируемому процессу предоставляется
одинаковый квант времени. пппиессов
В более сложных методах диспетчеризации вы I Р ГЬ1
происходит по приоритетам. В некоторых системах• подь-
определены заранее в соответствии с характером ‘ ддя
зователей. Задачей таких систем является обеспечение
каждого класса заданий необходимого уровня сервиса. В дру-
гих системах приоритеты могут назначаться самой операцион-
ной системой в целях увеличения производительности всей си-
стемы Приоритеты могут меняться и динамически в зависимо-
сти от загрузки и производительности системы. Возможно, что
няпялу с использованием системы приоритетов различным про-
иессам будут выделены различные кванты времени. Дальней-
по пение этих и более сложных способов диспетчериза-
Ц,ш может быть найдено в Дейтел (1984) и Лории (1981).
procedure WAITCESB)
ESBFLAG = 1 then (событие уже наступило)
возвратить управление запрашивающему процессу командой IPS
else
Ь<?9пометить запрашивающий процесс как Блокированной
занести запрашивающий процесс в ESBWJt Jr,
DISPATCH
end
а«
procedure SIGNAL(ESB)
ESBFLAG : = 1 (отметитьr что событие наступило}
for каждый процесс в ESBQUEUE do
begin
пометить процесс как Готовый
убрать процесс из ESBQUEUE
end
возвратить управление запрашивающему процессу командой LPS
б
Рис. 6.9. Алгоритмы обработки WAIT (SVC 0) и SIGNAL (SVC 1).
Когда активный процесс достигает точки, в которой ему
требуется ждать наступления некоторого события, он сообщает
об этом операционной системе при помощи запроса на обслу-
живание WAIT (SVC 0). О наступлении события, которого мо-
гут ожидать и другие процессы, операционной системе сообща-
ется посредством запроса SIGNAL (SVC 1). В разд 6.2.3 бу-
дут даны примеры использования WAIT и SIGNAL; здесь же
мы коснемся того, как эти запросы соотносятся с функцией
планирования процессов.
На рис. 6.9 приводится последовательность действий, выпол-
няемых операционной системой в ответ иа подобные сервисные
запросы. Событие, которое ожидалось или о наступлении кото-
рого было сообщено, определяется посредством задания адреса
соответствующего блока состояния события (ESB— Event Sta-
tus Block). Блок состояния события содержпг битовый флаг
ESBFLAG, в котором отмечается, произошло ли соответствую-
щее событие или нет. Блок ESB содержит также указатель иа
ESBQUELjL список процессов, ожидающих в этот момент
наступления данного события. Дальнейшая информация о ESB
примерах их создания и использования приводится в разд 62 3*
Запрос WAIT выдается активным процессом и говорит о
том, что процесс не может продолжить работу до наступления
события, соответствующего ESB. Таким образом, в алгоритме
обработки WAIT первым делом исследуется ESBFLAG и, если
событие уже наступило, управление возвращается запрашиваю-
щему процессу. Если событие еще не наступило, активный про-
цесс переводится в состояние блокировки и заносится в
ESBQUEUE.
Запрос SIGNAL выдается процессом, обнаружившим насту-
пление некоторого события, соответствующего ESB. Следова-
тельно, установкой ESBFLAG алгоритм для обработки SIGNAL
отмечает, что событие наступило. Затем осуществляется скани-
рование ESBQUEUE, списка ожидающих этого события процес-
сов. Каждый процесс в списке переводится из состояния блоки-
ровки в состояние готовности. Затем управление возвращается
процессу, сделавшему запрос SIGNAL.
Если используемый метод диспетчеризации основан на при-
оритетах, для обработки SIGNAL применяется несколько другой
алгоритм. В таких системах может случиться, что один или бо-
лее процессов, перешедших в состояние готовности, имеют более
высокий приоритет, чем текущий активный процесс. Учитывая
это, алгоритм для обработки SIGNAL вместо прямой передачи
управления активному процессу должен сначала вызвать дис-
петчер, который и передаст управление процессу с наивысшим
приоритетом, находящемуся в текущий момент в состоянии го-
товности. Этот способ называется планированием процессов по
приоритетам. Он позволяет процессу, перешедшему в состояние
готовности, перехватить управление у процесса, активного в
этот момент, по имеющего меньший приоритет, не ожидая и
течения кванта времени этого процесса.
6.2.3. Обслуживание ввода-вывода
На типичной мини-ЭВМ, такой как УУМ, ввод-вывод ое
ществляется побайтно. Например, для чтения данных ПРОГ!)3 1
ма должна иметь цикл, в котором опрашивается состояние у
ройства ввода-вывода и выполняется ряд команд чтения
ных. В подобных системах ЦП участвует в передаче и ПРШ
каждого байта с устройства ввода-вывода. Пример программи-
рования ввода-вывода такого рода показан на рис. 2.1.
В более совершенных ЭВМ, таких как УУМ/ДС, для ив
живания всех деталей передачи данных и управления
дом-выводом используются каналы ввода-вывода. На рис 6 10
приведена типичная для УУМ/ДС конфигурация ввода-вывода
Пусть, например существует 16 каналов, к каждому из которых
может быть подключено до 16 устройств. В номер, присвоенный
устройству ввода-вывода, входит и номер канала, к которому
оно подключено. Например, устройство, обозначенное 20--2F
подключено к Каналу 2.
Рис. 6.10. Типичная конфигурация ввода-вывода для УУМ/ДС.
Последовательность операций, которые должен выполнить
канал, задается канальной программой, состоящей из набора
канальных команд. Для осуществления операции ввода-вывода
ЦП выполняет команду ввода-вывода START I/O (SIO), в ко-
торой задается номер канала и начальный адрес канальной
программы. Затем канал выполняет указанную операцию вво«
да-вывода без дальнейшего вмешательства ЦП. По завершении
своей программы канал генерирует прерывание по вводу-выво-
ду. Одновременно могут работать несколько каналов, каждым
из которых выполняет свою собственную канальную програм-
му; таким образом, в одно и то же время могут осуществляться
несколько различных операций ввода-вывода. Каждый канал
работает независимо от ЦП, поэтому, пока выполняются опера-
ции ввода, ЦП может продолжать вычисления.
Операционная система ЭВМ типа УУМ/ДС вовлекается q
процесс ввода-вывода в нескольких случаях. Система должна
принять запросы на ввод-вывод от пользовательских программ
, и сообщить им, когда операции будут выполнены. Она можег
также управлять работой каналов ввода-вывода и обрабатывать
генерируемые ими прерывания. В оставшейся части раздела
мы обсудим, как эти функции выполняются, и проиллюстрируем
этот процесс несколькими примерами.
Программа на УУМ/ДС запрашивает операцию ввода-вы-
вода посредством выполнения команды SVC 2, параметрами
которой являются номер канала, начальный адрес канальной
программы и адрес блока состояния события, используемый
при оповещении о завершении операции ввода-вывода. Если
программа должна ждать результаты операции ввода-вывода,
то она выполняет команду SVC О (WAIT). Этой командой за-
дается адрес блока состояния события, соответствующего ожи-
даемой операции ввода-вывода. 1 аким образом, выполнение
операции ввода-вывода имеет вид
SVC 2 {запрос операции ввода-вывода}
SVC 0 {ожидание результата}
В некоторых случаях WAIT может следовать сразу за запро-
сом операции ввода-вывода. Однако, так как вычисления i
ввод-вывод могут идти одновременно, имеется возможность про-
должить выполнение программы, пока ожидаются результаты
операции ввода-вывода.
Более подробно это иллюстрируется программой на рис. 6 11.
Сначала программа загружает в регистры начальный адрес ка-
нальной программы, номер канала и адрес блока состояния
события. После этого для запроса операции ввода-вывода про-
грамма выполняет команду SVC. Канальная программа для
чтения, задаваемая в виде последовательности элементов дан-
ных, содержит две канальные команды. Первой командой зада-
ется операция чтения, которая должна быть выполнена на под-
соединенном к каналу устройстве с номером 1; 256 байт дан-
ных должны быть размещены в памяти, начиная с адреса
BUFIN. Вторая команда вызывает останов канала и генерпр\ 1
прерывание по вводу-выводу. Блок состояния события состою
из 3-байтовой области данных. Первым битом ESB являетея
флаг, используемый для индикации, наступило уже соотве -
ствующее событие или нет (0 = нет, 1 =да). Остальная час1 ь
ESB служит для сохранения указателя на очередь процессе'-
ожидающих это событие. Если ждущих процессов нет, то зна-
чение указателя равно нулю. Так, начальное значение
ESB Х'000000' показывает, что соответствующее событие еще ! -
наступило и что ожидающие его процессы отсутствуют. Да-"’
нейшие подробности, касающиеся формата канальных комав i
pi START
(инициализация.)
LDA ♦READ АДРЕС КАНАЛЬНОЙ ПРОГРАММЫ
LDS ♦ I НОМЕР КАНАЛА
LDT ♦ESB АДРЕС БЛОКА СОСТОЯНИЯ СОБЫТИЯ
sue 2 ВЫДАЧА ЗАПРОСА НА ЧТЕНИЕ
LOOP LDA ♦ESR АДРЕС ESP
SVC 0 ОЖИДАНИЕ КОНЦА ЧТЕНИЯ
{запись данник в рабочую область программна
LDA ♦0 ИНИЦИАЛИЗАЦИЯ ESP
STA ESR
LDA ♦READ
LDS ♦ 1
LDT ♦ESP
SVC 2 ВЫДАЧА СЛЕДУЮЩЕГО ЗАПРОСА НА ЧТЕНИЕ
. Сданные процесса)
J LOOP
КАНАЛЬНАЯ ПРОГРАММА ДЛЯ ЧТЕНИЯ
• ПЕРВАЯ КОМАНДА —
READ BYTE X'll' КОМАНДА = READ, УСТРОЙСТВО = t
BYTE X'0100' СЧЕТЧИК БАЙТОВ = 256
WORD BUFIN АДРЕС БУФЕРА ВВОДА
• .ВТОРАЯ КОМАНДА —
BYTE X'000000000000' ОСТАНОВ КАНАЛА
ESB BYTE X'000000" БЛОК СОСТОЯНИЯ СОБЫТИЯ ДЛЯ ЧТЕНИЯ
BUFIN RESB 256 БУФЕРНАЯ ОБЛАСТЬ ДЛЯ ЧТЕНИЯ
END
Рис. 6.11. Пример выполнения ввода-вывода с использованием запросов.
УУМ/ДС и блока состояния события, можно найти в прило-
жении В.
После выдачи запроса на ввод-вывод программа на
рис. 6.11 выполняет команду SVC 0. Регистр А содержит ад-
рес ESB, соответствующего ожидаемому событию. Таким собы-
тием в данном случае является только что затребованная опе-
рация ввода-вывода. После завершения операции чтения про-
грамма заносит введенные данные в рабочую облает!,. Затем
программа опять инициализирует ESB и запрашивает опера-
цию ввода-вывода для чтения следующих 256 байт данных.
Пока эта операция выполняется, программа может обпабаты-
вать уже прочитанные данные, совмещая тем самым функции
вычисления и ввода. По завершении обработки управление сно-
ва передастся на начало основного цикла для ожидания конца
следующей операции чтения. ца
Несколько более сложный пример приведен на рис G 12
В этом случае программа копирует 4096 байт записей даииит
С устройства 22 на устройство 14. Имеются две канальные про-
граммы: одна для чтения и другая для записи, а также два
блока состояния события. В основном цикле программы сначала
выдается запрос на чтение, а затем ожидается завершение это-
го чтения и предыдущей записи. По окончании обеих операций
программа создает последовательность вывода и выдает запрос
на запись. Однако в этот момент ESB для операции записи
имеет начальное значение Х'800000', где первый бит равен |
Этим отмечается, что соответствующее событие уже наступило
и при вызове стандартной программы WAIT операционной си-
стемы управление будет сразу возвращено программе пользова-
теля (рис. 6.9).
Операции ввода-вывода в программе на рис. 6.12 выполня-
ются независимо друг от друга, так как ими используючся
разные каналы. Одна операция может быть завершена раньше
другой. Возможно также, что обе операции будут выполнены
фактически одновременно. Программа в состоянии координиро-
вать взаимосвязанные операции ввода-вывода, так как им со-
ответствуют разные ESB. На примере этой программы показа-
но, как каналы могут использоваться для выполнения совме-
щенных операций ввода-вывода. Ниже такое совмещение будет
рассмотрено подробнее.
В программах иа рис. 6.11 и 6.12 показано, как осуществля-
ются запросы на ввод-вывод с точки зрения пользователя.
Сейчас мы готовы обсудить, как они в действительности обра-
батываются машиной и операционной системой. В аппаратуре
УУМ/ДС предусмотрено наличие в памяти, соответствующей
каналу ввода-вывода, рабочей области канала. В ней содер-
жатся стартовый адрес текущей канальной программы, если
она имеется, и адрес ESB, соответствующего текущей операции.
Результат работы операции ввода-вывода после ее завершения
отображается находящимися в рабочей области капала флаы-
ми состояния, такими как нормальное завершение, ошибка в.-,
да-вывода или устройство недоступно. Рабочая область пр'
граммы содержит также указатель на очередь запросов '
ввод-вывод для данного канала, которая поддерживается cia"
дартпыми программами операционной системы. Дополнив
ные сведения о том, где располагаются рабочие области
лов УУМ/ДС и что в них находится, содержатся в при-
жен и и В.
Р2 START 0
<инициализация >
LOOP LDA 40 ИНИЦИАЛИЗИРОВАТЬ ESB ДЛЯ ЧТЕНИЯ
STA RDESB
LDA ♦READ ВЫДАТЬ ЗАПРОС НА ЧТЕНИЕ С УСТРОЙСТВА 22
LDS ♦2
LDT ♦RDESB
SVC 2
LDA ♦RDESB ЖДАТЬ КОНЦА ЧТЕНИЯ
SVC 0
LDA ♦WRESB ЖДАТЬ ЗАВЕРШЕНИЯ ПРЕДЫДУЩЕЙ ЗАПИСИ
SVC 0
• * Сформирование последовательности вывода!
LDA ♦0 ИНИЦИАЛИЗИРОВАТЬ ESB ДЛЯ ЧТЕНИЯ
STA WRESB
LDA ♦WRITE ВЫДАТЬ ЗАПРОС НА ЧТЕНИЕ С УСТРОЙСТВА 14
LDS ♦ 1
LDT ♦WRESB
SVC 2
J LOOP
* ► КАНАЛЬНАЯ ПРОГРАММА ДЛЯ ЧТЕНИЯ
• ПЕРВАЯ КОМАНДА —
READ BYTE Х'12' КОМАНДА = READ, УСТРОЙСТВО = 2
BYTE Х'1000' СЧЕТЧИК БАЙТОВ = 4096
WORD BUFIN АДРЕС БУФЕРА ВВОДА
• ВТОРАЯ КОМАНДА —
BYTE X'000000000000' ОСТАНОВ КАНАЛА
• • КАНАЛЬНАЯ ПРОГРАММА ДЛЯ ЗАПИСИ
ПЕРВАЯ КОМАНДА —
WRITE BYTE Х'24' КОМАНДА = WRITE, УСТРОЙСТВО = 4
BYTE Х'1000' СЧЕТЧИК БАЙТОВ = 4096
WORD BUFOUT АДРЕС БУФЕРА ВЫВОДА
ВТОРАЯ КОМАНДА —
BYTE X'000000000000' ОСТАНОВ КАНАЛА
RDESB BYTE X'000000' БЛОК СОСТОЯНИЯ СОБЫТИЯ ДЛЯ ЧТЕНИЯ
WRESB BYTE X'800000' БЛОК СОСТОЯНИЯ СОБЫТИЯ ДЛЯ ЗАПИСИ
BUFIN RESB 4096 БУФЕР ВВОДА
BUFOUT RESB 4096 БУФЕР ВЫВОДА
END
Рис. 6.12. Программа, иллюстрирующая многократный запрос па ввод-вывод.
На рис. 6.13 отмечены действия, предпринимаемые операци-
онной системой в ответ на запрос ввода-вывода от программы
пользователя. Если требуемый канал занят выполнением другой
операции, операционная система ставит запрос в очередь к
нему. В противном случае она запускает канал, а текущий за-
прос сохраняет в рабочей области канала. Возможно также
что управление будет возвращено процессу, затребовавшему
ввод-вывод, и он, пока ведется обмен, сможет продолжить ра-
procedure lOREQ<CHAK,CP,£Sb)
опросить канал командой TIO
if канал занят then
постаешь <CP,ESB) в очередь к Каналу
else
begin
сохранить (СР„ESP) о рабочей области канала
запустить канал командой SIQ
end
возвратить управление запрашивающему процессу Командой LPS
Рис. G.13. Алгоритм обработки запроса па ввод-вывод (SVC 2).
На рис. 6.14 показаны действия, предпринимаемые операци-
онной системой в ответ па прерывание по вводу-выводу. Номер
канала, вызвавшего прерывание, находится в слове состояния,
procedure lOINTERRUPT(CHAN)
исследовать флаги состояния в рабочей области канала
if нормальное завершение операции then
begin
взять адрес ESB из рабочей области канала
командой SVC оповестить через ESB о
наступлении события
if очередь запросов к каналу не пуста then
begin
взять из очереди (СР,ESB> для следующего запроса
сохранить (CF'rESB) в рабочей области канала
запустить канал командой SI0
end Cif очередь не. пуста)
end Cif нормальное завершение операции)
else
выбрать подходящие действия по исправлению ошибок
if в момент наступления прерывания ЦП простаивал then
DISPATCH
else
возвратить управление прерванному процессу командой LPS
Рис. 6.14. Алгоритм обработки прерывания по вводу-выводу.
хранящемся в рабочей области данного прерывания. Д-1'1
деления причины прерывания операционная система исс.
флаги состояния в рабочей области канала. шпась
Если установлено, что операция ввода-вывода заг.
нормально, обработчик прерывания оповещает об этом ши
онную систему через заданный при запросе блок c°c™:!1 ,
бытия. Это может быть сделано как при помощи S\ СJ3‘ '“с|,; )
приводящего к вложенному прерыванию, так и непосредс
’:62 Машкино зависимые сп.,йства операционных систем
вызовом той части операционной системы, которая обрабатыва-
ет запросы SIGNAL. В любом случае окончание операции
да-вывода отмечается в ESB. Каждый ожидающий этого ппо"
цесс снова переводится в состояние готовности (см разд 6 9 91
Затем обработчик прерываний по вводу-выводу просматривает
очередь запросов к данному каналу и начинает выполнение
следующего запроса (если он есть). пс
Если флагами отмечено какое-то ненормальное состояние
то операционная система осуществляет соответствующие дейст-
вия по исправлению ошибок. Они, конечно, зависят от типа
устройства ввода-вывода и характера обнаруженной ошибки
Например, обработка ошибки четности при работе с магнито-
фоном обычно сводится к перемотке ленты назад и повторению
операции ввода-вывода (некоторое число раз). С другой сторо-
ны, когда кончилась бумага на печатающем устройстве, перед
попыткой осуществить дальнейшие действия по исправлению
ошибок оператору ЭВМ посылается сообщение. Если операци-
онная система обнаружит, что ошибка ввода-вывода неустрани-
ма, то она может окончить процесс, выдавший запрос на ввод-
вывод, и послать соответствующее сообщение пользователю.
Или, сохранив код ошибки в ESB, она может оповестить об
этом запрашивающий процесс, который сам уже может принять
решение, продолжить ему выполнение или нет.
После окончания работы обработчик прерываний обычно
возвращает управление прерванному процессу, восстанавливая
его состояние. Однако если ЦП в этот момент простаивал, то
должен быть вызван диспетчер. Делается это потому, что в
результате обработки прерывания некоторый процесс мог пе-
рейти в состояние готовности. Диспетчер будет вызван и в том
случае, если использовалось приоритетное планирование про-
цессов (см. разд. 6.2.2).
Выполнение всех функций обслуживания ввода-вывода и
планирования процессов демонстрируется на рис. 6.15. Два
пользовательских процесса, обозначенные Р1 и Р2, выполняют-
ся одновременно. Это те же процессы, что показаны на
Рис. 6.11 и 6.12. Л1ы считаем, что кванты времени, выделяемые
каждому процессу, достаточно большие; поэтому прерывание
йо таймеру до того, как процессу требуется отдать управление
по какой-то другой причине, обычно не происходит, г а дна
грамме рис. 6.15 показана последовательность действии, выпои
няемых центральным процессором, разделенным межд\ ПР
сами пользователей, частями операционной системы и Д •
каналами ввода-вывода. Начало шкалы времени на ди I *
Находится вверху. Величина промежутков на шкал^ бозна.
Цельно пропорциональна действительной длительное
чаемого ими времени. Последовательные номера призваны
м°чь в использовании данного примера,
Каналы
Блок обработки
прерываний по
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
(10)
ЦП
Г------------------------------------
Блок обработки
Pl Р2 Диспетчер SVC-лрерыеодй
В воду-вывод у
Комментарии-
Р1 запрашивает операцию В8одз-вывадэ(а;
Р1 ожидает завершения операции (а»
?2 запрашивает операцию ввода-вывода (б)
Р2 ожидает завершения операции (б)
ЦП начинает простаивать
(11)
(12)
(13)
(14)
.’15)
(16)
(17)
(18)
(19)
(20)
(21)
(22)
(23)
(24)
(25)
[26)
(27)
(28)
(29)
-30)
СМ)
(32)
$3)
Прерывание по вводу-выводу от канала Г
Сообщение о завершении (а)
Прерывание по вводу-выводу от канала 2
Сообщение о завершении (б)
pi запрашивает операцию ввода-вывода (в)
Операционные системы
Р1 ожидает завершения операции (в)
Р2 исследует ESB, в котором отмечено завершение операции
Р2 запрашивает операцию воодв-Вывода (г)
Y Р2 запрашивает операцию ввода-вывода (д)
Р2 ожидает завершения операции (Д)
I цп начинает простаиитв
/34)
(35)
(36)
(37)
(38)
(39)
(40)
(41)
(42)
(43)
(44)
(45)
(46)
(47)
(48)
(49)
(50)
(51)
(52)
(53)
(Д)
Прерывание по вводу-выводу от Канала 1
Сообщение о завершении (в)
Р1 запрашивает операцию ввода - ввода (е)
Прерывание ло вводу-выводу от Канала 2
Сообщение о завершении (д)
(е) Прерывание ло вводу-выводу от Канала 1
Сообщение о завершении (г)
Р1 ожидает завершения операции (е)
Р2 ожидает завершения операции (г)
(уже завершенной?
Рис. 6.15. Пример управления вводом-выводом и функции планирования процессов.
В начале примера процессы Р1 и Р2 уже инициированы-
Р1 был активизирован первым. Оба канала ввода-вывода сво-
бодны. В момент (1) процесс Р1, выполнив команду SVC, осу-
ществляет свой первый запрос ввода-вывода. Этим вызывается
прерывание, в результате которого управление передается бло-
ку обработки SVC-прерываний. Чтобы облегчить дальнейшие
ссылки, на диаграмме эта операция ввода-вывода помечена (а).
В запросе ввода-вывода задан свободный в этот момент канал
с номером 1. Поэтому после запуска блока обработки SVC-пре-
рываний канальной программы управление возвращается про-
цессу Р1 (момент 2).
В (3) выполнением другой команды SVC (SVC 0) Р1 вы-
дает для операции (а) запрос WAIT. Управление еще раз пе-
редается блоку обработки SVC-прсрываний. В ESB, заданном
этим запросом, отмечено, что ожидаемое событие еще не насту-
пило. Поэтому после перевода процесса Р1 в состояние блоки-
ровки вызывается диспетчер (4), который передаст управление
процессу Р2 (5). В момент (6) Р2 выдает свой первый запрос
ввода-вывода, предназначенный устройству 2 капала 2. Так как
канал 2 свободен, запускается операция ввода-вывода, а управ-
ление возвращается к Р2. В (8) Р2 должна ждать завершения
ввода-вывода; так как этого еще не произошло, Р2 блокируя]
ся. В (9), как и раньше, вызывается диспетчер. Однако в
этот момент оба процесса блокированы, поэтому диспетчер пе-
реводит ЦП в состояние простоя. Заметим, что оба канала
ввода-вывода по-прежнему активны.
Центральный процессор простаивает до момента (11), в ко-
торый канал 1 завершает операцию ввода-вывода. Канал гене
рирует прерывание, в результате которого ЦП выводится из
состояния простоя, а управление передается обработчику пре-
рываний по вводу-выводу. Определив, что операция заверши-
лась нормально, обработчик прерываний выдает для соответ-
ствующего ESB запрос SIGNAL (SVC 1).Тем самым управляв;
передается блоку обработки SVC-прерываний (12). Пропс
Р1, ожидающий изменения ESB, переводится в состоят
готовности. Затем блок обработки SVC-прерываннй возвра-
щает управление обработчику прерываний по вводу - в ы»0-
(13). Диспетчер, вызванный в момент (14), в момент (15)
редает управление процессу Р1. После завершения работы к--
нала 2 в (16) выполняется аналогичная последовательна
операций; в результате процесс Р2 переводится в состоянии
товности. Поскольку ЦП в момент прерывания не проста и;
управление Р2 сразу не передается, а возвращается оора"
чиком прерываний по вводу-выводу процессу PL Пропсы
не получит управления до тех пор, пока Р1 не выдаст в (—
следующего запроса WAIT.
343
Читателю, чтобы убедиться, что он хорошо понимает тонко-
сти передачи управления при различных прерываниях, следует
внимательно просмотреть весь пример до конца. Для этого бу-
дет полезно обратиться к алгоритмам на рис. 6.8, 6.9, 6.13 и
г М В особенности обратите внимание на разнообразие видов
Одновременной работы ЦП и выполнения операций ввода-выво-
я Обеспечение гибкого следования задании одно из основных
преимуществ операционной системы с прерываниями.
6 2.4. Управление реальной памятью
' Любая операционная система, поддерживающая одновремен-
работу более одного пользователя, должна обладать меха-
УпмоРм разделения центральной памяти между совместно вы-
процессами. Многие мультипрограммные снеге-
память на разделы (partitions) с выделением
ПОЛНЯЮЩИМИСЯ
мы разбивают
Задание Длина (шестнадца- теричная)
1 лооо
2 14000
3 Д800
4 4000
5 Е000
6 ВООО
7 СООО
В D00Q
для
Рис. 6.16. Задания
пользователей
примеров по распределению памяти.
каждому процессу своего раздела. Размер и расположение раз-
делов могут быть либо заранее заданы (разделы фиксирован
ного размера), либо назначаться динамически в процессе в
полнения заданий (разделы переменного Ра^1ср\''; паз.
Ниже рассматриваются некоторые способы у < • ,
делением памяти. В примерах будет исп^лв/°п полагается>
тельность заданий, приведенная на рис. • 1 ^ичество Одно-
что уровень мультипрограммирования( ' цен только числом
временно выполняющихся задании) о j <
самих заданий, загружаемых в це''1Т[)^,а"У'”1аП разделы фикси-
На рис. 6.17 показано разбиение памяти^шр ЭВМ
рованного размера. Полный о° * операционная система за-
предполагается равным 50 000 > другие разме-
нпмает первые 10 000 байт. Заметим, что эти J стна_.
ры и адреса, используемые в д таяРоперационной системой,
дцатеричном виде. Память, не дел j начинается с адрес
состоит из четырех раздел . ой и имеет длину
10000 сразу за операционнойс таком порядке: Разделы-
байт. Остальные разделы следуют
и 3 имеют по 10 000 байт каждый, а Раздел 4 — длину
8000 байт. А 1у
В простой схеме распределения с разделами фиксированного
размера каждое входящее задание загружается в наименьший
подходящий по объему раздел. Если размер раздела превосхо-
дит размер задания, то оставшаяся внутри раздела память не
используется. Система, имея вначале пустыми все четыре раз-
дела, первым делом загрузит Задание 1 в Раздел 2 Затем За-
дание 2 будет загружено в единственный достаточно большой
Раздел 1 - Раздел 2 - Раздел 3• Раздел 4 * Операцион- ная система toooo 28000 38000 48000 Операцион- ная система Операцион- ная система с U >перацион-1 *ая системз|
Задание 2 'ШШ. Задание 5 Задание 5 Задание 5 1
И вл 777/7-. ’' 'А. ////7s //7л
Задание I Задание 1 Задание 6 |Задание 6
шл.
жж W'W7/Vffl77>
Задание 3 Задание 3 Задание 3 Задание 7 мж
’ЯЛ W////////A 7 г
Задание 4 Задание 4 Задание 4 1 Задание 4
«Ж 7////7М7///7 «а
Оканчивается Оканчивается Оканчивается
Задание 2 • л Задание! Задание 3
э---------------► 6----------------► в---------------► Г
Рис. 6.17. Распределение памяти для заданий рис. 6.16 с использованием
разделов фиксированного размера.
для этого Раздел I. Задания 3 и 4 загружаются в Разделы 3
и 4. После этого все разделы оказываются занятыми, поэтому
больше заданий загрузить нельзя. Получившееся в итоге рас-
пределение памяти показано на рис-. 6.17а. Заштрихованные
области на диаграмме соответствуют неиспользованной памяти.
Однажды загруженное в раздел задание остается там
конца своего выполнения. После того как задание заверши гея,
занимаемый им раздел вновь становится доступным для ||С‘
пользования. На рис. 6.176 Задание 2 уже окончилось и в I’1 '
дел 1 было загружено Задание 5. На этом же рисунке показа-
ны дальнейшие действия, осуществляемые по мере того, к*11'
оканчиваются остальные задания.
Заметим, что сами разделы и их расположение остаю11 1
фиксированными вне зависимости от размеров занимающих
——•
заданий. Начальный выбор величины раздела в схеме с раз-
делами фиксированного размера очень важен. Число больших
разделов должно быть достаточным, чтобы длинные задания
могли выполняться без слишком большой задержки. Однако
если больших разделов слишком много, то при выполнении ко-
м -I -- -'«•••wwinvtiHH КО-
РОТКИХ задании значительное количество памяти расходуется
впустую. Использование разделов фиксированного размера паи-
10000
1А000
2Е000
38800
ЗС800
Операцион-
ная система
10000
Задание 1
Задание 2
Задание 3
Задание 4
1А000
38800
ЗС800
Операцион-
ная система
Задание 1
Задание 6
25000
2Е000
Задание 3
Задание 4
10000
1А000
Операцион-
ная система
25000
2Е000
Задание 6
Задание 3
Задание 4
38800
ЗС800
10000
1А000
Операцион-
ная система
Задание 6
25000
31000
38800
ЗС800
Задание 7
Задание 4
Задание 5
Задание 5
Задание 5
Задание 5
4А800к
4А800
4А800
Оканчивается
Задание 2
а -------------
Оканчивается
Задание 1
------------► 0
Оканчивается
Задание 3
Рис. 6.18. Распределение памяти для заданий рис. 6.16 с использованием раз-
делов переменного размера.
более эффективно, когда размеры большинства за^ Пязме-
дятся в пределах конкретных объемов, а распредс.‘о И(>
ров заданий меняется не часто. Это позволяет | р набора
пользовать доступную память посредством вь>
разделов ожидаемому множеству задании. множен
На рис. 6.18 демонстрируется выполнение! того же
ства заданий при использовании Рзздед^ новый раздел с
Для каждого загружаемого задания с окончания зада-
размерами, соответствующими заданию. ‘ может быть пе-
ния отведенная ему память освобожда
пользована при распределении дРУ™х р а операционной
Вначале вся память (кроме той, что• отведена он Р снных
системе) нс распределена, так как Р ся прн ег0 загрузке,
разделов. Раздел для Задания 1 н непосредственно за
Предположим, что этот раздел расположен 1
ею
операционной системой. Затем Заданию 2 отводится раздел,
следующий сразу за Заданием 1, и т. д. Объем свободной па-
мяти, оставшейся за Заданием 5, для загрузки очередного за-
дания уже недостаточен.
Когда завершается Задание 2, его раздел освобождается,
и новый Раздел отводится Заданию 6. Как показано на
рис. 6.186, этот новый раздел занимает часть памяти, которая
отводилась Заданию 2. Остаток от прежнего раздела Зада-
ния 2 остается свободным. Теперь имеются две несмежные сво-
бодные области памяти; однако пи одна из них не велика на-
столько, чтобы вместить еще одно задание. На рис. 6.18в и г
показано, как происходит освобождение и распределение памя-
ти по мере того, как оканчиваются другие задания.
При использовании разделов переменного размера нет на-
добности выбирать размер раздела заранее. Однако операцион-
ной системе, которая отслеживает, какие области памяти уже
распределены, а какие свободны, приходится проделывать боль-
шую работу. Обычно это делается системой при помощи под-
держиваемого ею связаного списка свободных областей. Этот
список просматривается при выделении нового раздела, который
размещается либо в первой {первое подходящее размещение),
либо в наименьшей {наиболее подходящее размещение) подхо-
дящей для него свободной области. Когда раздел освобождает-
ся, отведенная ему память объединяется со всеми смежными
свободными областями и заносится в список. Подробное обсуж-
дение и сравнение алгоритмов распределения памяти можно
найти в Стендиш [1980].
Вне зависимости от используемого способа создания разде-
лов необходимо, чтобы операционная система и аппаратные
средства обеспечивали защиту памяти. При выполнении зада-
ния в одном разделе недопустимо, чтобы оно изменяло ячейки
памяти другого раздела или операционной системы. В некото-
рых системах разрешено чтение данных из любой области па-
мяти, а запись—только внутри отведенного заданию раздела.
В других системах и чтение, и запись допускаются только в
пределах собственного раздела задания.
Для эффективной защиты памяти необходима и аппаратная
поддержка. Можно, например, ввести пару граничных регист-
ров, в которых будут содержаться начальный и конечный ад-
реса раздела задания. Эти регистры не доступны непосредо-
венно программам пользователя и могут быть использованы,
только если ЦП находится в режиме супервизора. Операцион-
ная система устанавливает граничные регистры, когда пользо-
вательскому заданию назначается раздел. Во время операции
контекстного переключения, аналогичных тем, что вызваны
командой LPS или прерыванием, содержимое этих регистров
автоматически сохраняется. Таким образом, граничные регис i*
ры всегда содержат адреса начала и конца раздела, отведенно-
го текущему активному процессу. При любом обращении к па-
мяти аппаратура автоматически сверяет адрес, по которому
идет обращение, с граничными регистрами. Если адрес
находится вне раздела текущего задания, обращение к
памяти не производится и генерируется программное пре-
рывание. и
В УУМ/ДС используется и другой способ защиты памяти.
Каждому 800-байтовому (в шестнадцатеричной системе счисле-
ния) блоку памяти ставится в соответствие 4-битовый ключ за-
щиты памяти. Эти ключи могут быть установлены операцион-
ной системой при помощи привилегированной команды SSK
(Set Storage Key — Установи ключ памяти). Каждый пользова-
тельский процесс имеет поставленный ему в соответствие 4-би-
товый идентификатор процесса, который хранится в поле ID
слова состояния SW. Когда заданию выделяется некоторый
раздел, операционная система присваивает ключам всех блоков
памяти внутри раздела значение идентификатора процесса
этого задания. При каждом обращении пользовательской про-
граммы к памяти аппаратура автоматически сравнивает иденти-
фикатор процесса из SW с ключом защиты адресуемого блока
памяти. Если значения этих двух полей не совпадают, то обра-
щения к памяти не происходит и генерируется программное
прерывание. Однако если ЦП находится в режиме супервизора,
то этой проверки не производится; операционная система мо-
жет обращаться к любой ячейке памяти.
Единой проблемой для всех общецелевых способов дина-
мического распределения является фрагментация памяти. Фраг-
ментация имеет место, когда доступная свободная память раз-
бита на несколько несмежных блоков, каждый из которых
слишком мал для использования. Рассмотрим, например,
рис. 6.18в. Чтобы разместить Задание 7, в целом имеется более
чем достаточно свободной памяти; однако из-за того, что нет
ни одного свободного блока достаточно большого размера, оно
не может быть загружено.
На рис. 6.19 показано одно из возможных решений этой
проблемы: использование перемещаемых разделов {relocatab е
partitions). После окончания каждого задания оставшиеся раз-
делы передвигаются как можно дальше к одному концу па^мяп
““ доступная свободная память собнра-
В результате этого вся —J-
ется в один общий блок, который больше подходит для рас |на-
деления новых разделов. Как показано на рис. 6.19, этот cnt)t
может привести к более эффективному использованию п' , '
по сравнению с тем, что достигается с помощью 11епс9с'‘
мых разделов. Однако копирование задании из одно< *
памяти в другое может потребовать значтслыю <. \
времени. Этот недостаток часто перевешивает преимущества
усовершенствованного использования памяти
При работе с перемещаемыми разделами’возникают пробле-
мы и с лерсместимостью программ. Рассмотрим, иапрнмео ппо
грамму, приведенную на рис. 6.20а. Команда ST А имеет пас
ширенный формат, поэтому она в оттранслированном bhV™
держит истинным адрес 08108. При использовании методов'
10000 1А000 2ЕООО *)QQ Л Л Операцион- ная система 10000 1А000 24800 28800 36800 41800 4D800 Операцион- ная система 10000 1А800 1Е800 2С800 37800 43800 Операцион- ная система 1 1» iooooI 14000b 22000 2D000 39000 Операцией- 1 1зя система |
Задание 1 Задание 1 Задание 3 Задание 4 |
Задание 5 Задание 6
Задание 2 Задание 3 Задание 4
Задание 5
Задание 4
Задание 5
Задание 3 Задание 6 Задание 7 Задание 8
Задание 6
Задание 7
JooUU ЗС800 4А800 Задание 4
Задание 5
4600С
—.
Оканчивается Оканчивается Оканчивается
Задание 2 Задание 1 Задание 3
а ---------—> 6 ----------------► в--------------► г
Рис. 6.19. Распределение памяти для заданий рис. 6.16 с использиианк'. л
перемещаемых разделов.
описанных в гл. 2 и 3, это адресное поле будет отмене с
семблером. Чтобы получить истинный адрес, по которое
гружена программа, значение адресного поля модицнщпру
загрузчиком. Например, если начальная загрузка ,.ос-/...
ствлена по истинному адресу 2Е000, то адресное поле
STA, как показано на рис. 6.206, будет изменено наi -3j
Предположим теперь, что раздел, содержащий
[начинаться не с адреса 2Е000, как на рис. 6.19а, с.а; \ ,
1А000, как на рис. 6.196. Тогда адрес в команде S1A оуд
неверным. Действительно, он будет указывать на ячейку
ти, которая является частью раздела, отведенного друюму
Данию. Аналогичная проблема возникнет, если РЗ загрузи
базовый регистр адрес некоторой своей части или соз, *
структуру данных, использующую указатель адреса. Нос.и
чальной загрузки программы все перемещаемые значения oil
Адрес Исходный оператор
0000 РЗ START О
J840 +STA BUFF2
OF108108
END
а
Объектный код
Регистр
2Е000
2F840
36108
а
Рис. 6.20. Использование регистра перемещений при вычислении адреса.
8108 BUFF2 . . .
делены ассемблером, что упрощает перемет исполь<
Однако во время своего выполнения програм> < ' g
зовать регистры и ячейки памяти произвольнь. определить,
щем случае операционная система не в сосго Р типами
какие значения являются адресами, а ‘ '?ц0 время вы-
данных. Таким образом, перемещение пр р ’ начальной
полпенни осуществить намного сложнее, чем после
загрузки.
Применение перемещаемых разделов на практике требует
некоторой аппаратной поддержки. Один из обычно используе-
мых для этого способов показан на рис. 6.20в. В этом случае
существует специальный регистр перемещения, устанавливае-
мый операционной системой и содержащий начальный адрес
текущей активной программы. Во время операций контекстного
переключения содержимое этого регистра автоматически сохра-
няется или восстанавливается, а при перемещении программы
на новое место его значение изменяется операционной системой.
При любом обращении программы пользователя к памяти зна-
чение, содержащееся в регистре перемещения, автоматически
складывается с адресом. Например, команда STA па рис. 6.20в
обращается к адресу 08108; однако, учитывая регистр пере-
мещения, истинный адрес, к которому осуществляется обраще-
ние, равен 36108. Если начало программы РЗ было перенесено
на адрес 1А000, как показано на рис. 6.20г, то операционная
система изменит значение регистра перемещений для РЗ на
1А000. Таким образом, адрес, к которому действительно обра-
щается команда STA, будет равен 22108.
Важно понять, что регистр перемещения управляется опера-
ционной системой; пользовательской программе он не доступен.
Таким образом, этот регистр в корне отличается от задаваемых
программно базовых регистров, имеющихся в УУМ/ДС, Sy-
stem/370 и многих других ЭВМ. Регистр перемещения автома-
тически включается каждый раз, когда программа обращается
к какой-нибудь области памяти; этим достигается тот же эф-
фект, что и при фактической загрузке каждой программы с
истинного адреса 00000. И в самом деле, на многих ЭВМ для
программы пользователя не существует прямого способа опре-
делить ее реальное месторасположение в памяти. Таким обра-
зом, этот тип перемещений применим к адресам, находящимся
в указателях структур данных, к значениям в базовых регист-
рах, равно как и к адресам в командах. Заметим также, что
подобное автоматическое перемещение, выполняемое аппарату-
рой, полностью исключает необходимость перемещения про-
грамм загрузчиком.
В этом разделе были рассмотрены методы распределения
программных разделов с заранее определенными размерами.
В некоторых операционных системах программам пользователей
во время их выполнения разрешается динамически запрашивать
дополнительную память. Дополнительно выделяемая память нс
обязательно должна быть смежной с первоначально назначен-
ным разделом. Подобное динамическое распределение памяти
обычно осуществляется методами, схожими с теми, что исполь-
зовались при управлении памятью для структур данных.
I i0Qftmee изложение этих методов можно найти в Стенд**111
1 * I ,
-_____-2 МашНЯН0.зависимыр 1
6.2.5. Управление виртуалТ™~^~-------~--5
Виртуальным (virtual) назы
вательской программе представляется пГУРС’ Ко™Рый польза
отличными от тех, что он в дейс?ГИт? ЛаДаЮ1Цим свойствам,
рим, например, рис. 6.21. Программ! ЛЬНости имеет. Рассмот
большую виртуальную использоват!
ным адресным пространством. Его объем м ж "Н°ГДа в11^^
м М0Жет Даже превосхо-
Внешняя память
Реальная
память
Виртуальная
память
Рис. 6.21. Основная концепция виртуальной памяти.
дить всю доступную реальную пак аммой> хранится на
виртуальной памяти, использке. 1 памяТ11) По иеобхо-
некотором внешнем устройстве^ ( отображаются в ре аль-
димости части этой виртуальной < отображении в ре-
ную память. Ни о внешней памяти «« о « 'написана так,
"0СВ этом разделе мы рассмотрим. одни
лизании виртуальной памяти -Р03^ ‘ру. содержащую
(demand paging). Ссылки на едены в “"“'^ная
других видов виртуальной тоаннц по запросу . р Уировая-
В системе с размешени с^раницы некоторой ни1(Ные
память процесса разделена / разделена Любая
ПОЙ длины. Реальная память цт0 „ странии«руЖепа,
кадры (page frames) топ 11|аЛыю может ' „пестрая™
страница любого процесса I »памяти. От< I
любой страничный кадр реальной
352
Объектный
Стр. °
Стр. I
Адрес DQQOQQ исходный оператор код
F3 START Q
* 00Q103 +JEQ SKJPl 33X00420
• • • SKIP! *LVA BUFFI 03X0GFFA
• • 001S40 5KIP2 +STA виггг oFioaioa
.Стр. 2
002020
002024
+Л.Т
4
SKIPS
SKIP2
3B104A0Q
3F2915
Стр. 3
Стр. 4
004AOQ
SKIP3 LDX
#В
050008
О04А20
-iSTA
виш.х
СГЭО&ГГА
Рис. 6.22. Программа, иллюстрирующая
размещение
страниц по запросу.
в страничные кадры описывается таолицей отоб/ш.^ 0
страниц (РМТ — Page Map Table)-, для каждого проиеа •
системе имеется одна РМТ. Таблица отображения cipai
пользуется аппаратурой для преобразования адресов вир >•
ной памяти программы в соответствующие адреса реалыюп
мяти. Процесс преобразования похож на использование ри
ра перемещений, рассмотренного в предыдущем разделе.
ко здесь для каждой страницы в РМ.Т имеется свое зна’н-
Стр. 7
Адреа
DO6FFA
008108
Исходный оператор
BUffl R£$W
8UFF2 RE3W
Объектный
код
Стр. 8
Стр. 9
Стр. Л <. « .
00A80Q END
Рис. 6.22. Продолжение.
Такой перевод виртуальных адресов в реальные называется
динамическим преобразованием адресов.
Рассмотренные понятия иллюстрируются пРогРа*1М°" "а
рис. 6.22. Программа разбита на страницы длиной 1000 (11114
надцатеричный) байт. Виртуальные адреса с 0000 по
принадлежат Странице 0, адреса с 1000 по IMF —
це I и т. д. Когда начинается выполнение программы, операци-
онная система загружает Страницу 0, содержащую псрчю <-
полняемую команду, в некоторый страничный кадр рс<. >
памяти. Остальные страницы загружаются в память по мере
ЙЙДОбНОСТИ. onrnVQkH
Процессы динамического преобразования адрес >в _
страниц иллюстрируются рис. 6.23а. СтРа™и °рСа^„ой па.
загружена в страничный кадр Ш (т. е. в аДР 1 v
мяти с ID000 по IDFFF). Рассмотрим сначалакоманду Л.Ч.
находящуюся по виртуальному адресу 010 . Р
(Виртуальный адрес)
1D000
10103
1DFFF
1 (Виртуальный адрес) т
Д---------0420 ।
I
I
I
JСтраницам смещение *4201
1
• !
-------------- 1
33100420-----I
I
Г
I
I
I
I
I
!
I
I
1
I
!
(
t
4----------1D42O
(реальный адрес)
Динамическое преобразова-
ние адресов
(Виртуальный адрес)
6
У_________________Гл- 6 Операционные системы
Рис. 6.23. Примеры динамического
преобразования адресов и размещения
страниц по запросу.
этой команды —
имеет смещение 420 от ее начала. В таблице Тобважения
страниц показано, что Страница 0 программы загружена »
страничный кадр 1D (начинающийся с адреса 1D000). Таким
образом, реальный адрес, вычисленный при динамическом ппе
образовании адресов, равен 1D420. 1
Рассмотрим далее команду LDA с виртуальным адресом
0420. Ее операнд расположен по виртуальному адресу 6FFA
(Страница 6, смещение FFA). Однако эта страница в реаль-
ную память еще не загружена, поэтому аппаратные средства
динамического преобразования адресов вычислить реальный
адрес не могут. Вместо этого они генерируют специальный тип
программного прерывания, называемого прерыванием по отсут-
ствию страницы или страничным прерыванием (рис, 6.236).
В ответ на это стандартная программа обработки прерывании*
которая будет рассмотрена позже, загружает требуемую стра-
ницу в некоторый страничный кадр. Предположим, что его но-
мер— 29. После этого заново выполняется команда, вызвавшая
прерывание. На этот раз, как показано на рис. 6.23в, динами-
ческое преобразование адреса проходит успешно.
Остальные страницы программы загружаются в случае не-
обходимости подобным же образом. Предположим, что на
рис. 6.22 показаны все команды перехода (JUMP) в програм-
ме, равно как и все команды, операнды которых находятся на
других страницах. Когда управление передается от последней
команды на Странице 0 первой на Странице 1, операция вы-
борки команды вызывает страничное прерывание, в результате
которого загружается Страница 1. Команда STA с виртуаль-
ным адресом 1840 вызывает загрузку Страницы 8. Затем в ре-
зультате выполнения цикла выборки команд загружается Стра-
ница 2, так же как перед этим Страница 1. Рассмотрим теперь
две команды JUMP с адресами 2020 и 2024. Осуществление
первого из этих переходов (т. е. условие «меньше чем » истин-
но) вызывает загрузку Страницы 4; иначе же Страница 4 оста-
ется незагруженной. В последнем случае команда безусловного
перехода с адресом 2024 передает управление на ячейку Стра-
ницы 1 (которая уже загружена). После передачи управления
на Страницу 4 выполняется команда STA с адресом 4А20. гло
задается адрес 6FFA операнда с индексной адресацией. 11Рел’
положим, что содержимое индексного регистра равно 8. 1огда
целевой адрес равен 7002 и выполнение команды приводит >.
загрузке Страницы 7.
На рис. 6.24 показана ситуация, возникшая после тольх
описанных событий. По таблице отображение страниц можно
судить, что Страницы 0, 1, 2, 4, 6, 7 и 8 загружены, в с
_ --- - । ранни
мента загрузки были модифицированы (здесь
8). Эта информация используется г.г.,.
личных прерываний при выталкивании
даны также соответствующие номера страничных кадров. Для
каждой программы в системе имеется аналогичная таблица
Заметим, что в ней указаны также и страницы, которые с мо-
------------------------------------------* — Страницы 7 и
программой обработки стра-
’“"Ц страницы из памяти.
Рис. 6.24. Отображение виртуальное — реальное с использованием таолип
Сражения страниц.
Рис. 6.25 суммирует продемонстрированные выше функции
преобразования адресов и размещения страниц по запрос}. 11
рис. 6.25а дан алгоритм динамического преобразования адресов
Напомним, что он реализован непосредственно аппаратн.
средствами машины. Если динамическое преобразование а -
сов не может быть завершено потому, что требуемой страны
в памяти нет, происходит страничное прерывание.
па рис. 6.256 показана программа обработки прерывания.
Рванного отсутствием страницы. Операционная система со*
ТЭ6ЛИЦУ’ 011ИСЬ1ВаюшУю состояние всех страничных к ад-
ров. 1а первом шаге обработки прерывания таблица просмаI-
357
ривается в поисках свободного страничного калпа р
найден, требуемая страница может быть загоужХия °”
но. В противном случае страница, находящаяся в ДЛе“'
жна быть вытолкнута, чтобы освободить место для той’ Д°Л*
procedure DAT Греализуеная аппаратно} ’ ^ОТО»
разложить виртуальный адрес на (номер страницы, смещение)
найти вхождение для этой страницы в РМТ
if страница находится в памяти then
begin
объединить (адрес страничного кадра, смещение)
для создания страничного кадра
if это команда "store" then
пометить в F'Ml, что страница модифицирована
end Cif страница находится в памяти)
else
вызвать страничное прерывание
а
procedure PAGEFAULT {реализуется как часть операционной системы}
сохранить состояние процесса из рабочей области прерывания
пометить процесс как Блокированный
if имеется свободный страничный кадр then
begin
выбрать свободный страничный кадр
пометить выбранный кадр в таблице страничных кадров как Занятый
разрешить все прерывания командой LPS
end Cif имеется свободный страничный кадр!
else
begin
выбрать страницу для выталкивания
пометить выбранный кадр в таблице страничных кадров как Занятый
разрешить все прерывания командой LPS
if выбранная страница была модифицирована then
begirt
обновить РМТ И таблицу страничных кадров
выдать запрос на ввод-вывод, чтобы переписать страницу
во внешнюю память
ждать завершения операции записи
end £if страница была модифицирована}
end tif нет свободного страничного кадра}
выдать запрос на ввод-вывод для чтения страницы
в выбранный страничный кадр
Ожидать завершения операции чтения
Обновить РИТ и таблицу страничных КЗДР0&
пометить процесс, как Готовый
восстановить состояние пользовательского
процесса, вызвавшего страничное прерывание
6
Рис. 6.25. Алгоритмы динамического преобразования адресов и обработки
страничных прерываний.
рую требуется загрузить. Если выталкиваемая страница с мо<
мента загрузки была модифицирована, то ее новая версия дол-
жна быть переписана во внешнюю память (backing store). Если
нет, то она может быть просто уничтожена.
Программа обработки страничных прерываний, показанная
на рис, G.256, требует выполнения по крайней мере одной
операции ввода-вывода. Поэтому для ее работы нужно намного
больше времени, чем для любого другого обработчика прерыва-
нии из рассмотренных нами выше. Часто бывает нежелательно
закрывать прерывания на длительное время. Ясно например
что предпочтительнее во время страничного обмена дать воз-
можность использовать ЦП другим программам. Для управления
подобным мультипрограммированием требуется, чтобы прерыва-
ния были разрешены. Поэтому при прерывании по отсутствию
страниц сначала определяется, какое действие требуется вы-
полнить, и сохраняется информация о состоянии прерванного
затем в течение оставшегося времени обработки
разрешается функционирование системы прерываний.
Сложнее производится выбор обработчиком прерываний
страничного кадра для записи требуемой страницы. Кадр по-
мечается как занятый, чтобы он не был выбран в следующий
раз. Для того чтобы информация о состоянии не была унич-
тожена во время следующего прерывания, обработчик прерыва-
ваний берет ее из рабочей области прерывания программы и
процесса, а
Сложнее
сохраняет в некотором месте, отведенном данному процессу
Затем, загрузив слово состояния, отличающееся от текущего
SW тем, что в нем установлены в «1» все биты MASK, обра-
ботчик прерываний включает систему прерываний. Остальная
часть программы обработки прерываний функционирует так же,
как и пользовательский процесс: для инициирования операции
ввода-вывода и ожидания результатов их выполнения она дела-
ет SVC-запросы. После завершения операции обмена страниц
обработчик прерываний, используя сохраненную информацию о
состоянии, снова передает управление на команду, вызвавшую
прерывание.
В алгоритме, приведенном на рис. 6.256, не учтены некото-
рые важные моменты. Самый очевидный из них — какую стра-
ницу вытолкнуть из памяти. В некоторых системах хранятся
записи, фиксирующие последнее обращение к каждой странице:
выталкивается та, что дольше не использовалась. Это так на-
зываемый метод выталкивания дольше всего не использовс
шейся страницы (LRU— Least Recently Used). Чак как на-
кладные расходы при таком способе хранения записей мог
быть высокими, для LRU используются простейшие виды •
проксимации. В других системах делаются попытки определю
множество наиболее часто используемых страниц опраш
мого процесса (так называемое рабочее множество пропек
В подобных системах выталкивание страницы производят я
ким образом, чтобы каждый процесс всегда имел в n
свое рабочее множество. Обсуждение и развитие разлия^
стратегий выталкивания страниц можно найти в Дейтел I
Другой вопрос, оставленный без ответа, связан с реал»-'*
ей самих страничных таблиц. Одно из возможных решении
ключается в их реализации в ___.
мяти. В качестве указатет» иаВИДе Масснвов в центп-..,
процесса используется некотош iV*10 РМТ ТекУШего чкт?" "а'
операционной системой. Этот метод моТТ₽’ устанавлнвХ°мй
тивным, потому что для каждого преобп^п°Казаться неэффе
ется быстрый доступ к памяти. Однакоа3вВи^,Я адРес°в треб5-
этот способ используется В сочетании ? в,,™ Торых системах
фером. служащим для улучшении среднего СКОрост,1ы« бу.
Другая возможность заключается в peanS,, “РСМ?"" Доступа,
жения страниц при помощи специальной ВЬХ Табл"и °™б₽а.
социативной памяти. Такой способ очень ,11 0СК0Р0СТ|10« ас-
оказаться слишком дорогим для систем А Т™0™’ "° м»*>'т
ламятью-„^^«^«Дение этнхИр^Х.КЫ,оП
лизации РМТ может быть найдено в Дейтел^ [1984].
Системы с размещением страниц по запросу избегают нера-
ционального использования памяти в основном при помощи
фрагментации, часто связанной со способами организации раз-
делов. Память можно экономить и другими способами. Напри-
мер, стараются не загружать те части программы, которые в те-
чение определенного времени выполнения не используются От-
нако системы с размещением страниц по запросу имеют и тугие
уязвимые места. Например, предположим, что обращение к
слову в центральной памяти занимает 1 мкс, а считывание
страницы из внешней памяти — в среднем 10 мс (10000 мкс).
Предположим также, что в среднем для всех заданий в систе-
ме только 1 из 100 обращений к виртуальной памяти вызывает
страничное прерывание. Даже при такой очевидно малой вели-
чине страничных прерываний система хорошо работать нс бу-
дет. На каждые 100 обращений (требующих 100 мкс) система
потратит 10 000 мкс на считывание страниц из внешней памяти.
Таким образом, вычислительная система тратит приблизительно
99 % своего времени на свопинг страниц и только 1 % па по-
лезную работу. Этот полный разлад в работе называется про-
буксовкой (thrashing).
Во избежание пробуксовки в только что описанной операции
необходимо, чтобы число страничных прерываний было намного
меньше (возможно, порядка одного прерывания на каждые
10 000 обращений к памяти). На первый взгляд может пока-
заться, что для достижения приемлемой производительности
нее программные страницы должны находиться в памяти.
Однако это необязательно. Благодаря свойству, называемом,'.
локальностью ссылок, которое можно наблюдать в реальных
программах, обращения к памяти не распределены случайно по
Всему виртуальному адресному пространству программы, ме
сто этого они имеют тенденцию к группированию в адрес! «
пространстве, как показано на рис. 6.26а . Это нроисхо. .
из-за таких общих свойств программ, как последи • с.
выполнение команды, компактное кодирование циклов, последо-
вательная обработка структур данных и т п
Благодаря локальности ссылок можно достичь приемлемо
малого числа страничных прерываний, не храня все алпесное
пространство программы в реальной памяти. На рис Г>Ж
гипотетической программы величина страничных ппеоы»я2
дана как функция от числа страниц программы, содержацихс
в памяти. Масштаб этой кривой для разных программ сильно
Число страниц в памяти
Рис. 6.2G. а — Локализованные обращения к памяти (каждая точка —это
ячейка памяти, к которой было осуществлено обращение в данный момент
времени в процессе выполнения программы); б — Эффект локализации
ссылок в зависимости от числа страничных прерываний.
варьируется, однако ее поведение типично для многих реаль-
ных программ. Часто, как и в данном примере, существует
критическая точка W. Если в памяти содержится меньше W
страниц, наблюдается пробуксовка. Если в памяти находятся
W страниц или больше, то производительность будет удовлет-
ворительной. Значение этой критической точки W и является
размером рабочего множества страниц программы, о котором
говорилось ранее. Дальнейшее обсуждение результатов, связан-
ных с размерами рабочего множества и пробуксовкой, можно
найти в Дейтел [1984] и Лорин [1981].
Размещение страниц по запросу даст еще один пример <'-
ложенной связи (delayed binding): соответствие между адресами
виртуальной и реальной памяти не устанавливается до момеша
обращения к памяти. Такая задержка требует дополнительных
расходов (на динамическое преобразование адресов, считывание
страниц и т. п.). Однако для программиста пня
ся более удобной, а также обеспечить эффективное Гмспп™33™'
ние реальной памяти. Можно сравнить эти замечай, 30Ва'
что были сделаны в предыдущих примерах по отложенимJ™”’
зям (разд. 3.4.3, 5.3.1 и 5.4.2). сложенным свя-
. Выше была рассмотрена реализация виртуальной памяти
при помощи размещения страниц по запросу Другой тип п
туальной памяти можно реализовать посредством сегментной
организации памяти (сегментации). В системе с сегментной
организацией виртуальной памяти адрес состоит из номера сег
мента и величины смещения внутри него. Принципы отображе-
ния и динамического преобразования адресов аналогичны рапсе
рассмотренным. Однако сегменты могут иметь произвольную
длину (в отличие от страниц, длина которых в каждой системе
фиксирована). Кроме того, сегменты обычно соответствуют ло-
гическим блокам программы, таким как процедуры или обла-
сти данных (в отличие от страниц, которые обычно являются
результатом произвольного разбиения адресного пространства).
Это дает возможность связать такие атрибуты защиты, как
только чтение или только выполнение, с конкретными сегмен-
тами. Возможно также разделение сегментов между различны-
ми заданиями пользователей. Сегментная организация памяти
часто используется вместе с размещением страниц по запросу.
При этом имеет место двухуровневая процедура отображения и
преобразования адресов. Дальнейшую информацию по сегмент-
ной организации памяти и ее реализации можно найти в Дей-
тел [1984], Лорин [1981] и Мэдник [1974].
6.3. Машинно-независимые свойства
операционных систем
В этом разделе будут кратко рассмотрены некоторые общие
функции операционных систем, непосредственно не зависящие
от архитектуры машины, на которой они функционируют, ти
свойства могут быть реализованы на более высоком уровне ш
сравнению с рассмотренными ранее. Поэтому они нс ‘_
фундаментальны с точки зрения основного назначс!
ционных систем, как вопросы аппаратной ПОДД^Р ’ 1 ет
репные в предыдущем разделе. Объем книгн 11 _ " больше
"а
ЛИТВРразлУ'6.2.3 были РЗ“мотРснывВр3аздЖб‘зе1
логичиыйе₽^роМс ВЛТ 6o“TBUCBoKPo‘roX- уровня: ‘ управление
логическими файлами и работа с ними. В разд 632 обсуждает-
ся проблема планирования, т. е. выбора из заданий пользова-
телей кандидатов на обслуживание, производимое на более
низком уровне, о чем говорилось ранее.
В разд. 6.3.3 рассматривается основной объект расппетепе
ния ресурсов, осуществляемого операционной системой и воз
никающие при этом сложности. Наконец, в разд. 6.3.4 вводятся
такие важные понятия, как защита и безопасность операцион-
ных систем.
6.3.1. Работа с файлами
Данный раздел посвящен некоторым функциям, выполняе-
мым типичными операционными системами в процессе управ-
ления и работы с файлами. В большинстве систем программы
пользователей имеют возможность запрашивать ввод-вывод при
помощи средств, описанных в разд. 6.2 (канальных программ и
SVC-запросов). Однако это достаточно неудобно, так как про-
граммисту должны быть известны коды канальных команд и
их форматы, а программе пользователя — номера каналов,
устройств и, возможно, реальный адрес требуемой записи, если
используется устройство с прямым доступом (например, диск).
Кроме того, нужно отслеживать окончание ввода-вывода, вы-
полнять буферизацию и объединение в блоки, о чем будет ска-
зано ниже.
Функция управления файлами, осуществляемая операцион-
ной системой, является промежуточным звеном между програм-
мой пользователя и супервизором ввода-вывода (рис. 6.27).
Программа пользователя на логическом уровне с помошыо
имен файлов, ключей и т. п. делает запросы, например «прочи-
тать следующую запись из файла F». Программа управления
файлами реализует метод доступа, транслируя логические за-
просы в физические запросы на ввод-вывод (т. е. канальные
программы), и передает их супервизору, действующему при
управлении операцией ввода-вывода (разд. 6.2.3).
Чтобы перевести логические программные запросы в каналь-
ные программы, система управления файлами должна иметь
информацию о расположении и структуре файлов. Эту инфор-
мацию она получает из структуры данных, называемой катало-
гом, и файловых информационных таблиц. В действительности
термины, используемые для обозначения подобных струм}Р-
так же как и их форматы и содержание, в разных операцион-
ных системах различны. Каталог устанавливает соответсгю
логических имен файлов с их физическим местонахождением
может предоставить о файлах некоторую общую информации’-
В файловой информационной таблице содержится дополни!ель
ная инфюрмацця, например, об организации файлов, длннь
6.3. Машинно-независимые св .йстт операционных систем зад
записи и форматах, о способе индексирования, если оно имеет-
ся. Чтобы начать работу с файлом, система просматривает ка-
талог и определяет местонахождение соответствующей файло-
вой информационной таблицы. Система также может создать
буфера для размещения в них блоков файлов, которые будут
прочитаны или записаны. Эта процедура называется откры-
тием файла. После окончания работы с файлом буферные
и другие рабочие области и указатели уничтожаются. Такая
процедура называется закрытием файла.
Рис. 6.27. Использование программы управления файлами для ввода-вывода.
Одной из наиболее важных функций управления файлами
является автоматическое выполнение операций буферизации и
объединения в блоки читаемых и записываемых файлов. Па
рис. 6.28 эти операции иллюстрируются последовательно вводи-
мым файлом. Предполагается, что чтение записей осуществля-
ется программой пользователя последовательно с начала файла
и до его конца. Логически файл состоит из записей длиной
1024 байт; физически, однако, файл образован 8192-байтовыми
блоками, каждый из которых содержит 8 логических записей. ।
Этот вид объединения записей в блоки обычно осуществляется |
конкретными типами запоминающих устройств в целях эконо- |
мии времени обработки и пространства памяти. Подробнее об I
этом говорится в Лумис [1983].
На рис. 6.28а показана ситуация, сложившаяся после того,
как файл был открыт и программа пользователя осуществила
свой первый запрос на чтение записи. Система управления фай-
лами уже выдала запрос на ввод-вывод для чтения в буфер
В1 первого блока файла и должна ждать завершения этой опе-
рации, прежде чем сможет передать требуемую запись поль-
зователю. На рис. 6.286 первый блок прочитан. Он находится
в буфере В1 и содержит логические записи с номерами от \
Рис. 6.28. Блокирование и буферизация последовательного файла.
буемую запись ппУ ^пРавления файлами может передать трс-
устанавливается пользователя. Для чего указатель Р
буфер В2 втоппгл г РВУ!? лог»ческую запись. Для чтения в
выдает втопой (||И' лока Файла система управления файлами;
выдает второй физический запрос на ввод-вывод.
прос на3 чтенирЗММа пользователя в следующий раз делает за-
либо действий записи’ Уже нет необходимости ждать каких
Указатель Р пя п° ВВОДУ'ВЬ1В°ДУ- Система просто передвигает
пользователю - огическУю запись 2 и возвращает управление
ЧТО Физическая Га операция показана на рис. 6.28в. Заметим,
ка в 6vd)en Р9 опсрация ввода-вывода по чтению второго бло-
1 все еще выполняется. Те же действия повтор'1'
--------63 “»»™>-»еэ..»еМше свойства о„ерщ„0„„и> CUCTt|| 3)i5
(рис. 6.28г)ДЛЯ ДРУГИХ 'ЛОГ“Ч“К'“ з«"»сей первого 6лока
Если программа пользователя осуществляет запрос in чт„
шге 9-и записи до завершения операции ввода-вывода лл» г.
ка, системе управления файлами снова приходится заставит.'
программу ждать. После того как второй блок прочитав vKa
затель Р переводится на первую запись буфера В2 П'
этого система управления файлами выдает запрос на вво i кп
вод для чтения в буфер В1 третьего блока и процесс пполол
жается подобно тому, как было описано выше. Заметим что
использование двух буферных областей позволяет совмещать
работу с одним блоком и чтение другого. Подобный способ ча-
сто называемый двойной буферизацией, широко используется
при обмене последовательными файлами.
В предыдущем примере программа пользователя осущест*
вляла просто серию запросов на чтение записей, ничего не зная
о буферизации и деталях выполнения физических запросов па
ввод-вывод. Сравните это с программой на рис. 6.11. которая
выполняет схожую функцию буферизации, имея дело непосред-
ственно с супервизором ввода-вывода. Ясно, что использование
системы управления файлами сильно упрощает программу, об-
легчает ее написание и, следовательно, уменьшает число воз-
можных ошибок. Не требуется и повторение во многих про-
граммах одних и тех же кодов.
Программы управления файлами выполняют также много
других функций: распределение пространства на внешних запо-
минающих устройствах, реализацию правил управления досту-
пом к файлам и их использованием. Дальнейшее обсуждение
этих вопросов можно найти в Дейтел [1984] и Мэдник [1974],
6.3.2. Планирование заданий
Планирование заданий — это выбор заданий пользователей
для выполнения. В однопрограммной системе оно сводится к
определению порядка выполнения заданий. В мультипрограм-
мной системе планировщик определяет порядок входа заданий в
решение.
На рис. 6.29а показана типичная двухуровневая сиск. <
планирования в мультипрограммной системе. Задания, посту-
пающие в систему, помещаются в очередь входных за
которой они затем выбираются планировщиком задании.
ранные задания становятся активными; это означаетчт
начинают принимать участие в операции планиров ' я
сов, описанной в разд. 6.2.2. Двухуровневая ПРОЦС‘^1? '* е
в целях ограничения уровня ^льтипроерамм^^
числа заданий пользователей, между которыми iр - -1 1
деление ЦП и других системных ресурсов. Это необходимо дл
поддержания эффективной работы мультипрограммной системы.
Если система пытается выполнять одновременно слишком мно-
го заданий, перекрытие при управлении ресурсами становится
слишком большим, а количество доступных каждому заданию
ресурсов — слишком малым. В результате производительность
системы снижается.
В только что описанной схеме планировщик заданий исполь-
зуется в качестве инструмента для поддержания требуемого
уровня мультипрограммирования. Однако этот идеальный уро-
6
Рис. 6.29. а— Двухуровневая система планирования и б —трехуровневая
система планирования.
вень может меняться в зависимости от характера выполняю-
щихся заданий. Рассмотрим, например, систему, в которой для
управления памятью применяется стратегия размещения стра-
ниц по запросу. Количество заданий, одновременно использую-
щих реальную память, по существу, не ограничено. Выполнять-
ся может любое задание, имеющее по крайней мере одну стра-
ницу. Однако, когда в памяти у задания отсутствует некоторое
критическое число страниц, начинается пробуксовка, и от этою
страдает производительность всей системы. К сожалению, ip. q
но заранее определить то количество выделяемых заданна’
страниц, которое позволит избежать пробуксовки. Вдобавок
течение выполнения программы оно может сильно меняться, ।
этому во время работы системы может меняться и требуем!'!
уровень мультипрограммирования.
Если входная очередь не пуста, уровень мультипрограммн
вания достаточно просто можно увеличить, обратившись к н '•
нировщику заданий. Труднее бывает его уменьшить, напри"1
для того, чтобы остановить пробуксовку. Это обычно достигай!
СЯ при помощи процедуры трехуровневого планирована,
нин, которая показана на рис. 6.296. Плаппровн Гi,?'
планировщик процессов (т. е. диспетчер) паботя,пт . 1 11,1 11
нее. Однако существует также планировщик промежиточшХ
уровня, управляющий производительностью систем/, „
требуется, регулирующий уровень мультнпрограммироваюм
Если он слишком высок, промежуточный планировщик по h L .
ет его, приостанавливая или свертывая одно или несколько^'
даний. Если уровень мультипрограммирования слишком ши, '
промежуточный планировщик возобновляет работу приостанор'
ленных заданий или обращается к планировщику заданий ,/й
того, чтобы активизировать новые. Промежуточные птанипог
щики могут использоваться и для регулирования приоритет
диспетчеризации активных заданий, основываясь на иаблю те-
нии за ними в процессе выполнения.
Вся система планирования обычно базируется на системе
приоритетов, предназначенных для достижения определенных
целей. Первой пелыо может быть, например, получение макси-
мальной пропускной способности системы, т. е. выполнение наи-
большей вычислительной работы за кратчайшее время. Ясно,
что для этого требуется эффективное использование всех си-
стемных ресурсов. Другая задача — получение наименьшего
среднего времени прохождения, т. е. времени между загрузкой
задания пользователем и завершением его выполнения. С си-
стемами разделения времени связана задача минимизации
предполагаемого времени ответа (времени между нажатием
клавиши ENTER на терминале и получением на это ответа си-
стемы).
Существует и много других задач планирования. Например,
мы можем захотеть обеспечить гарантированный уровень об-
служивания посредством ограничения максимально возможного
времени прохождения и времени ответа. Пли справедливости
ради предоставить всем одинаковый уровень обслуживания.
С другой стороны, исходя из внешних причин, возможно, потре-
буется предоставить определенным заданиям наивысший при-
оритет. В некоторых системах у пользователей имеется возмож-
ность за большую цену получить более высокий приоритет, в
этом случае целью планирования может быть заработать по-
больше денег.
Первые две задачи, упомянутые выше,— высокая пропускная
способность и малое среднее время прохождения и время от-
вета— обычно принимаются в качестве желательных свойств
системы. К сожалению, они часто несовместимы. Рассмотрим,
например, систему разделения времени, работающую с большим
числом терминалов. Мы можем решить, что обеспечить л}41
время ответа нужно посредством более быстрого перок.
управления между различными терминалами пользова е. <
Для этого ори диспетчеризации каждому процессу можно вы-
делять меньшим квант времени. Однако это приводит к увел -
ченню частоты операции контекстного переключения что за
ставляет операционную систему чаще принимать решения по
распределению ЦП и других ресурсов. Это означает что на
кладные расходы операционной системы будут выше’а впемя
предоставляемое заданиям пользователей,- меньше’ поэтом^
пропускная способность в целом уменьшится ’ у
Задание 1
Задание 2
Т, =2
Т2 = 5
— ТСр — 3,5
J_______I_______I________L
2 3 4 5
Время (в минутах)
Задание 1 — — — — — Т, = 4,5
Т2 = 4,3
Задание 2 ------ — - — тср = 4,4
_________I 1 I I I__________
1 2_3_4_5
Время (в минутах)
6
Рис. 6.30. Сравнение времени прохождения и пропускной способности для
а — однопрограммной системы, б — для мультипрограммной системы.
пакетной обпЛпР v РассмотР"м однопрограммную снстечу-
ются два заланияК"п ^аким образом в этой системе выполни-
на ипомея- v t k M „ П0Ка3аН0 |,а ₽ис- 6-30а- Обратите внимание;
тальных лшшях Ремен" (°ни показаны пробелами на горнзон
^росташал Fon,, ?ТВеТСТВуЮЩПХ Заданням 1 и 2), когда ЦП;
то воемя n'nnvn- - °$Э задания запущены в момент времени 0,
прохождения Задания (Т,)гравн0 2 мин’ а Bpc),il
дения Т nanwrx ог Я 2 (Ь) —5 мин. Среднее время прохож-
дения |ср равно 3,5 мин.
одновоемечи^1 Л?ПеРЬ мУльтипРОгРаммную систему, в которой
Гис 6 306 о >полняются Два задания, как это показано и
коисход^г такТмТЬп1ЛТ0 Разделен»е ЦП между заданиях
i астся это Ра3°м, что полное время простоя умень
i -с. 6 15 И. .J м°МеН’ П0Х0Жнй «а тот, что показан
меньшего времени простоя два задания запер-
тся быстрее: за 4,5 мин вместо 5 мин. Это означает, что про-
111310 Д способность системы стала больше: тот же самый объем
ПУГпты был сделан за меньшее время. Однако среднее время
пппхождения задания стало хуже: 4,4 мин вместо 3,5 мин.
Р Как правило чаще всего используются две стратегии плани-
пования заданий: первым пришел - первым обслужен
Р?-Дгс __ first Come —First Served)" и кратчайшее задание —
(SJF — Shortest Job First). Стратегия FCFS стремится
ЖСживать все задания одинаково, минимизируя тем самым
впемя прохождения; SJF обеспечивает снижение среднего вре-
Хи прохождения, так как короткие задания могут вынужденно
ожидать Обслуживания в течение долгого времени. Примеры
ожидаю v других стратегии планирования мож-
?Ю84Ь Лорин и'эвЦ, Мэдиик (.974),
6.3.3. Распределение ресурсов
В разд. 6. 2 обсуждалось, каким образом операционная си-
стема может управлять такими ресурсами, как центральная
память, каналы ввода-вывода и ЦП. Эти ресурсы используются
всеми заданиями пользователей; распределение осуществляется
системой автоматически. Ниже будет рассмотрена более общая
функция распределения ресурсов, выполняемая многими опера-
ционными системами. Ее можно использовать для управления
распределением таких ресурсов пользователя, как файлы и
структуры данных. На рис. 6.31а при помощи двух программ
иллюстрируется необходимость применения этой функции. Обе
программы используют последовательный стек, созданный ка-
кой-то третьей программой. Внешние переменные STACK и ТОР
содержат соответственно базовый адрес стека и относительный
адрес элемента данных, находящегося в его вершине. Предпо-
лагается, что внешние ссылки на переменные STACK и ТОР
обрабатываются методами, аналогичными рассмотренным в
гл. 3. Программа Р1 добавляет данные в стек; для этого она
увеличивает предыдущее значение ТОР на 3, заносит содержи-
мое регистра А в вершину стека, а затем запоминает новое
значение ТОР (строки 24—27). Программа Р2 изымает дан-
ные; для этого она заносит значение из вершины стека в ре-
гистр А и уменьшает затем значение ТОР па 3 (строки 37
40). Для простоты мы не использовали команду, требуемую
для обработки пустого стека и переполнения.
Если процессы Р1 и Р2 выполняются одновременно,то они мо-
гут работать как правильно, так и неправильно. Предположим,
например, что текущее значение ТОР равно 12. Если выполнятся
команды с номерами 24—27 программы Р1, то в байты
’’ Такая стратегия обслуживания часто называется FIFO. — Прим. рсд.
1 Р1 START 0
2 EXTREF STACK ЛОР
3 LDS ♦3 РЕГИСТР S = КОНСТАНТА 3
24 +LDX ГОР
25 ADDR s,x
26 ♦STA STACK,x
27 ♦STX TOP
ВЗЯТЬ УКАЗАТЕЛЬ ВЕРНИНЫ СТЕКА
УВЕЛИЧИТЬ ЕГО ЗНАЧЕНИЕ
ДОБАВИТЬ В СТЕК НОВОЕ ДАННОЕ
СОХРАНИТЬ НОВОЕ ЗНАЧЕНИЕ УКАЗАТЕЛЯ
40 END
i Р2 START 0
2 EXTREF STАСК,TOP
3 LDS #з РЕГИСТР S = КОНСТАНТА 3
37 +LDX TOP ВЗЯТЬ УКАЗАТЕЛЬ ВЕРШИНУ СТЕКА
38 +LDA STACK,X ВЗЯТЬ НОВОЕ ДАННОЕ ИЗ СТЕКА
39 SUBR S,X УМЕНЬШИТЬ ЗНАЧЕНИЕ УКАЗАТЕЛЯ
40 +STX TOP СОХРАНИТЬ НОВОЕ ЗНАЧЕНИЕ УКАЗАТЕЛЯ
END
a
Рис. 6.31. Управление ресурсами и использование сервисных ты
рационной системе.
станет равно '15 °Если НОВОе данное- а значение ТОР
40 программы Р2, то тоГькп ЛУТж?“П“,ген“. команды 37—
считано, а значение ТОР ’силобавленн°е Р1 данное будет
лит правильная работа Р1 и Р9- ^НВТ ₽авным |2' Так ВЬ'Г-1Я'
буемые операции нал г™™ 1 оба пР°Песса выполняют тра-
вильная последовательность паб6 ВЛ«ЯЯ Д₽уг на друга' Пра'
чала Р2 выполнит стооки Ч7Р буДет и тогда> когда сН?‘
Теперь предположим 3 40’ а затем Р^-строки 24-27.
кончается отведенный ей "Т° П0СЛе вьшолнения строки 24 у Г1
вант времени. Происшедшее в резуль-
1
2
3
оп.рацИо„„ых
Pt START 0 '—
,E2IRE₽ ®TACK»TOP
tts «3 ₽етет „ . константа 3
22
23
24
23
26
27
28
LDT SVC SHAME 3 ЖЖ™ m “
-шос ADDR *STX SVC TOP s,x STACK,X TOP 4 ДОБАВИТЬ В СТЕК НОВОЕ ДАННОЕ СОХРАНИТЬ НОВОЕ ЗНАЧЕНИЕ ШЗАТЕГТ ОСВОБОДИТЬ РЕСУРС УКАЗАТЕЛЯ
47 SNAME bYTE 'STACKl'
48 EN£1
1 P2 START 0
2 EXTREF STACK,TOP
3 Uis *3 РЕГИСТР S = КОНСТАНТА 3
35 LDT ’’STKNH УСТАНОВИТЬ УКАЗАТЕЛЬ НА ИМЯ РЕСУРСА
36 SVC 3 ЗАПРОСИТЬ РЕСУРС
37 +LUX ТОР ВЗЯТЬ УКАЗАТЕЛЬ ВЕРШИНЫ СТЕКА
38 +LDA STACK,X ВЗЯТЬ НОВОЕ’ ДАННОЕ ИЗ СТЕКА
39 SUBR s,x УМЕНЬШИТЬ ЗНАЧЕНИЕ УКАЗАТЕЛЯ
40 +STX TOP СОХРАНИТЬ НОВОЕ ЗНАЧЕНИЕ УКАЗАТЕЛЯ
41 SVC 4 ОСВОБОДИТЬ РЕСУРС
74
STKNH
BYTE
END
'STACKl
S.
Рис. 6.31. Продолжение.
тате этого прерывание
:„.v от таймера вызовет сохранение значении
всех регистров; сохраненное значение регистра л б)дет равно
12. Предположим теперь, что Диспетчер передает управле .
которая затем выполняет строки 37—40. Так как зт „3
программой Р1 еще не было изменено, B03bMJ q Когда
б^йтЬв 12-14 стека и сделает значение ТОР равным Когда
Р1 снова получит управление ЦП, регистр / <-
содержать значение 12. Таким образом, в результате выполне-
ния строк 25—27 в байты 15—17 стека будет добавлено новое
данное, а значение ТОР установлено в 15.
Последовательность только что рассмотренных событии при-
ведет к неправильной работе Р1 и Р2. Данное, считанное Р2
по-прежнему как бы является частью стека, и получается, что
стек содержит па одно данное больше, чем должно быть. Не-
правильные результаты получаются и в некоторых других слу-
чаях. Такие ситуации могут возникать всякий раз, когда два
одновременно работающих процесса пытаются обменяться од-
ним и тем же файлом или структурой данных.
Избежать ситуаций такого рода можно, монополизировав
управление стеком на время выполнения операций модифика-
ции каждой из программ. На рис. 6.316 показано типичное ре-
шение проблемы, при котором используются запросы на обслу-
живание операционной системе. Выполнением команды SVC 3
программа Р1 запрашивает монопольное управление стеком.
Требуемый ресурс задается регистром Т, указывающим на ло-
гическое имя (определяемое пользователем), присвоенное стеку.
После добавления в стек нового данного и изменения ТОР Р1
отказывается от монопольного управления, выполнив команду
SVC 4. Программа Р2 осуществляет аналогичную последова-
тельность действий.
Операционная система в ответ на запрос управления ресур-
сом проверяет, назначен ли он какому-нибудь другому процес-
су или нет. Если ресурс свободен, то управление передастся
запрашивающему процессу. Если ресурс занят, то система пе-
реводит запрашивающий процесс в заблокированное состоя-
ние, в котором он находится до тех пор, пока ресурс не станет
доступным. Пусть, например, в данный момент свободен ресурс
STACK1. Если Р1 запросит его (строка 23), то управление
операционной системой будет возвращено непосредственно этой
программе. Как и раньше, предположим, что сразу после вы-
полнения строки 24 заканчивается квант времени, выделенный
PI. Затем управление ЦП переходит к Р2; однако STACK!
остается занятым Р1. Таким образом, после запроса Р2 ресур-
са STACK1 в строке 36 программа будет переведена в состоя-
ние блокировки. В конце концов Р1 снова получит управление
и завершит работу со стеком. Когда Р1 освободит STACK!
(строка 28), он будет передан Р2, которая из состояния блоки-
ровки перейдет в состояние готовности и после получения ''
равления ЦП сможет выполнить операцию модификации. С
тателю следует внимательно просмотреть последовательной
этих событий, чтобы увидеть, как с помощью данного мск11
удается избежать возникновения описанных выше проблем-
К сожалению, использование операций запроса и отка-,л
может привести к проблемам другого рода. Рассмотрим, наш"*
2 3 LDT sue • =R1 3 ЗАПРОС RESI
4 LDT =R2 ЗАПРОС RES2
5 SVC 3
9 •
6 LDT =R2 ОСВОБОЖДЕНИЕ
7 SVC 4
8 LDT =R1 ОСВОБОЖДЕНИЕ
9 SVC • 4
10 R1 BYTE 'RESI*
11 R2 BYTE 'RES2'
12 END
1 Р4 START • 0
2 LDT =R2 ЗАПРОС RES2
3 SVC 3
• •
А LDT *=R1 ЗАПРОС RESI
5 SVC 3
6 LDT =R1 ОСВОБОЖДЕНИЕ
7 SVC • 4
8 LDT =R2 ОСВОБОЖДЕНИЕ
9 SVC 4
10 R1 BYTE 'RESI'
•11 R2 BYTE 'RES2'
12 END
RES I
RES2
потенциальной
ресурсов, приводящий к
RES2
RES1
самоблокировке.
Рис. 6.32. Запрос
мер, программы на рис. 6.32. Первой УП,^^С1111^ pCCC^[?s2.
RESI запрашивает РЗ; позже она запрашив ' 'n£S2 она
Программа Р4 использует те же два ресурса, однако RL52
запрашивает перед RESI. ПЛ™иярт управление
Предположим, что РЗ после запроса у времени конча-
ресурсом RES1; при этом отведенный ейквант i 1 3 можст
«ся ло того, как она сможетд3атребовзf RES2J„
быть активизирована Р4. Предположим,
получает управление ресурсом RES2. Такая последовательность
событий ведет к ситуации, в которой дальше не смогут выпол-
мяться ни РЗ, ни Р4. Действительно, программа Р4, дойдя до
строки 4, затребует управление ресурсом RES1, после чего она
будет переведена в состояние блокировки, так как RES1 отдан
РЗ. Аналогично РЗ, дойдя до строки 4, затребует управление
RES2 и тоже будет переведена в состояние блокировки, так как
RES2 отдан Р4. Поскольку свободных ресурсов нет, ни один
процесс не сможет продолжить работу.
Такая ситуация является примером взаимоблокировки (de-
adlock); она характеризуется тем, что в некотором наборе про-
цессов каждый отдельный процесс постоянно заблокирован, так
как необходимые ресурсы заняты другими процессами. Взаимо-
блокировка снимается освобождением ресурса за счет удаления
из решения одного или нескольких вовлеченных в нее заданий.
Существует ряд методов, позволяющих избежать взаимоблоки-
ровки. Например, система может потребовать, чтобы процесс
запрашивал все свои ресурсы одновременно или делал это в
определенном порядке (как то: RES1 перед RES2). К сожале-
нию, при этом из-за продолжительной занятости ресурсов сни-
зится работоспособность всей системы. Описание методов на-
хождения и предотвращения взаимоблокировок можно найти в
Дейтел [1984].
Выше рассмотрены частные случаи общих проблем взаимо-
исключения и синхронизации процессов. Их обсуждение и спо-
собы разрешения можно найти в Дейтел [1984] и Холт [1978]
6.3.4. Защита
Во всякой операционной системе, обслуживающей одного или
нескольких пользователей, должны существовать средства, обес-
печивающие защиту отдельного пользователя от возможных не-
санкционированных действий других. Например, пользователь
должен иметь возможность создавать файлы, которые не могут
быть прочитаны или изменены другими пользователями. В це-
лом проблема безопасности и защиты достаточно сложна.
В данном разделе будут коротко рассмотрены основные функ-
ции защиты, выполняемые типичной операционной системой.
Они должны быть совмещены с безопасностью на физическом
уровне, с административными процедурами и другими способа-
ми контроля, осуществляемыми для обеспечения эффективно.!
защиты. Дополнительную информацию по защите, безопасности
и секретности можно найти в Дейтел [1984], Деннинг [198. I
и Фернандес [1981].
В большинстве многопользовательских операционных систем
существует некоторый вид контроля доступа или авториз^
ции\ чаще всего они реализуются на основе матрицы доступ^
375
систем
аналогичной той, что показана на пис в зз п
пользователи обозначены и2 и J п~?3’ В этом "Римере
отношению к некоторому объекту (файлу илиП°ЛЬЭОВателя ™
даются строками в матрице доступа Так ™ пРогРа"ме) за-
жет читать файлы /, 1г, * "тУь"ав ф^лп?л“^«ль Ui мо.
грамму р2. Однако ему запрещен какой nJ ВЫполнять про-
/= или программе р„ Права’ Та досту",к6° ™ступ * «А
объекту обычно определяются его создателем R созданн™у
схемах пользователям, обладающ„м^™Т,п,ымТ^’“иТ
Файлы
Пользо* ft f? f|
ватели г- — —
с < л л СП Е
Uj н Е
Ц, RM R R.E
Рис. 6,33. Пример матрицы доступа.
доступ, разрешено передавать их другим пользователям. До-
ступ к контролируемым объектам осуществляется при помощи
запросов на обслуживание операционной системе. Каждому
пользователю, авторизация которого произведена неверно, в
доступе будет отказано.
В действительности матрица доступа достаточно разрежена.
Большинство пользователей имеет доступ к относительно ма-
лому числу объектов системы. По этой причине информация,
связанная с правами на доступ, часто хранится в виде списка
авторизаций для каждого объекта (т. е. списка авторизованных
пользователей) или списка возможностей (т. е. списка объек-
тов, к которым возможен доступ). Дальнейшую информацию по
реализации модели матрицы доступа можно найти в Деннинг
[1983].
Эффективность только что описанного метода зависит, оче-
видно, от правильной идентификации пользователей. С тем чтобы
применить верные правила контроля за доступом, операци-
онная система должна иметь возможность распознавать каждое
го пользователя. Один из наиболее часто используемых спосо-
бов идентификации — системные пароли. В большинстве систем
пользователю для запуска задания необходимо ввести секрет
ный пароль или зарегистрироваться с помощью интерактивно
терминала. Иногда этот способ применяется шире и подт р
дение пароля требуется для доступа к конкретным »
программам и т. п. В некоторых системах имеетеi
таблица паролей, используемая операционной си
проверки паролей, получаемых от пользователей, од ,Я|ПМТЫ
является потенциально уязвимым местом всей снсте- '
Во избежание этого во многих операционных систем'.
хранится в зашифрованном виде. Более подробно об этом
и других подобных методах можно узнать в Деннинг |19»3].
Так как информация иногда должна находиться вне средств
защиты, система идентификации и авторизации пользователей
нс всегда позволяет разрешить все проблемы, связанные с без-
опасностью. Рассмотрим, например, рис. 6.34а. Идентификация
и авторизация пользователя за интерактивным терминалом про-
изведены правильно. Мы предполагаем, что вычислительная си-
стема осуществляет соответствующий контроль доступа и имеет
средства обеспечения безопасности на физическом уровне.
Рис. 6.34. Использование кодирования данных для их защиты во время пе-
редачи.
Предполагается также, что и сам терминал на физическом
уровне защищен. Однако линию связи между вычислительной
системой и терминалом защитить бывает сложно или вообще
невозможно. (Примером может служить проблема предотвра-
щения подслушивания, когда терминал связан с ЭВМ через
обычную телефонную сеть.) Это означает, что во время переда-
чи уязвимой является любая информация из файла F, которая
передается терминалу. Аналогично можно узнать все пароли,
посылаемые пользователем, а следовательно, получить доступ
к защищенным объектам.
Обычно проблемы такого рода решаются с помощью ишф'
ровки данных^ Информация, которая должна быть передана по
незащищенной линии связи, зашифровывается (кодируется), ко-
гда она еще находится в пределах средств защиты. Переданная
информация расшифровывается (декодируется) уже под защи-
той соответствующих средств получателя. Прослушивающий не
сможет понять передаваемую зашифрованную информацию
Операции шифровки и дешифровки одинаково успешно могут
выполняться как аппаратурой, так и программным обеспече-
нием. Способов шифровки существует много. Для более под-
робного ознакомления с этими методами смотрите Деннинг
[1983].
Конечно, эффективность любой системы защиты всецело за-
висит от правильности и защищенности ее самой. В рассмотрен-
ной нами системе информация по контролю за доступом долж-
на быть защищена от неавторизованных изменений. Должен
существовать и механизм, обеспечивающий невозможность до-
ступа пользователей к защищенным объектам, минуя систему
безопасности. В этой связи часто бывают полезны такие аппа-
ратные средства, как режимы пользователя/супервизора, при-
вилегированные инструкции и механизм защиты памяти. Очень
важно быть уверенным и в том, что часть операционной систе-
мы, связанная с правилами защиты (ядро безопасности) функ-
ционирует правильно. Дальнейшее обсуждение этих вопросов
может быть найдено в Дейтел [ 1984], где есть и обзор слабых
мест в средствах обеспечения безопасности операционных си-
стем, и интересные и поучительные случаи по вскрытию за-
щиты системы.
6.4. Способы построения операционных систем
В этом разделе будут вкратце рассмотрены некоторые важ-
ные вопросы, касающиеся создания операционных систем и их
структуры. В разд. 6.4.1 вводится понятие операционной систе-
мы с иерархической структурой, используемой при построении
многих реальных систем. В разд. 6.4.2 показано, как операци-
онная система может поддерживать многочисленные виртуаль-
ные машины. С их помощью у пользователя создается впечат-
ление, что он работает па выделенной ему части аппаратных
средств. Разд. 6.4.3 посвящен мультипроцессорным операцион-
ным системам; в нем обсуждаются некоторые способы распре-
деления заданий между процессорами.
6.4.1. Иерархическая структура
Многие реально существующие операционные системы раз-
работаны и реализованы на основе иерархической структуры.
Примеры подобной структуры приведены на рис. 6.35. В этом
случае основным принципом, как видно из рис. 6.35а, является
обобщение идеи расширенной машины, приведенной на рис. 6.1.
Каждый слой, или уровень, в структуре может использовать
Уровень Функции
3 Управление файлами
2 Управление памятью
I Управление вводом-выводом
О Диспетчеризация, управление
ресурсами
6
Рис. G.35. Пример системы с иерархической структурой.
фуивдпи, предоставляемые ему более низким уровнем, как ecin
сто ™ 1ТЛ1,С-Ь Т™° реалЫ10Й машины- Так. Уровень 0 ча-
дело непоепме' Ядром (kernel'> операционной системы, имеет
С аппаРатУР°й; Уровень 1 имеет дело с
пользователя Х™™”'"" Ур0?нем °’ и т- д‘ Программы
НЯ (в пянмпм ЮТ Де\7° С ннтеРФейсом самого высокого уров-
интеосЬейс пппк?УЧЭе Ровня 3)> который представляет собой
НаФппг «qS еЛЯ’ Рассм°тренный в разд. 6.1.
Рассматпппярмг," показаны функции, соответствующие уровням
взаимоотношении структуры. Их расположение определяется
В общем cnxuia междУ выполняемыми ими операциями,
лишь к djvnriir ° ^уикции каждого уровня могут обращаться
«бравом *Уе In “ ™Z° Же или более '"«“го уровня; таким
прогоаммкт иппЛЖН° быть внешних вызовов. В нашем примере
буферов должны^иепп* $айлами (вровень 3) для распределения
а дляг чтения и ™п, пользовать менеджер памяти (Уровень 2),
управление памятг блоков супервизор ввода-вывода. Если
ление памятью производится при помощи размещения
страниц но запросу, то менеджер памяти для пеоелачи
между реальной памятью и вспомогательной тожепп СТраниц
зывать супервизор ввода-вывода. Все уровни система ВЫ’
зуют предоставляемые Уровнем 0 функции плаиипоия ис"оль-
цессов и управления ресурсами. "" иРования про-
У иерархической структуры много преимуществ Системные»
программы на каждом уровне могут использовать относит^™
простые функции и интерфейсы, предоставляемые более ничю?
ми уровнями. Программисту нет необходимости вникать в то
как они в действительности реализуются. Операционная систе-
ма может быть создана и отлажена по уровням, начиная с ну-
левого. Это сильно снижает сложность каждой части системы
и намного упрощает реализацию заданий и их отладку.
На рис. 6.356 показано типичное расположение функций, од-
нако различные системы существенно отличаются друг от дру-
га. Рассмотрим, например, программы обработки прерываний.
Во многих системах обработчики прерываний первого уровня
(FLIH— First-Level Interrupt Handlers) размещены в ядре
(Уровень 0). После начальной обработки прерываний FLIH
может передать управление программе более высокого уровня;
это исключение из правил, согласно которым внешние вызовы
недопустимы. Так, например, FLIH в случае прерывания по
отсутствию страницы может сохранить информацию о состоя-
нии, разрешить другие прерывания, а затем передать управле-
ние программе Уровня 2 (см. рис. 6.25в).
В некоторых операционных системах иерархическое распре-
деление функций в особых случаях сделано более сложным.
Информацию об этом и о других примерах иерархических
структур можно найти в Лорин [1981] и Питерсон [1983].
Иерархические системы различаются также правилами пе-
редачи управления с одного уровня на другой. В строгой
иерархии каждый уровень может обращаться только к уровню,
находящемуся непосредственно под ним. Так, Уровень 3 может
связываться только с Уровнем 2. Если программе управления
файлами в нашем примере необходимо вызвать супервизор вво-
да-вывода, то этот запрос будет передан с Уровня 2 на . ро-
вень I. Преимущество этого подхода заключается в простоте
использования: каждый уровень взаимодействует только с од
ним интерфейсом. Однако такое ограничение может привести
потере эффективности, так как возрастает число вызовов, ко
торые нужно сделать для достижения внутреннего \ров .
В прозрачной иерархии (transparent hierarchy) каждый ур
вень может связываться непосредственно с интерфейсом; Л1
более низкого уровня. Так, например, программа 2ОЛ^ vnon-
может обращаться к программам управления Фаил
ня 3 или непосредственно вызывать функции суперв
да-вывода Уровня 1.
Дальнейшее обсуждение иерархических структур операцион-
ных систем можно найти в Питерсон 119831Лопин 119811 и
Мэдник 11974J. Jiii
6.4.2. Виртуальные машины
Чтобы перед пользователями создать иллюзию того, что они
работают на автономных виртуальных машинах, концепцию
иерархической структуры, рассмотренную в предыдущем разде-
ле, можно расширить. Подход, связанный с применением вир-
туальных машин, делает возможной одновременную работу раз-
личных операционных систем на одной и той же реальной ма-
<?2
« СП
О м
У
<22
Операционная
система
0С1
Операционная
система
0С2
Операционная
система
осз
(тест)
Пользователь^
(автономная
программа)
Монитор виртуальной машины (МВМ)
Реальная машина
Рис. 6.36. Операционная система с виртуальными машинами и многими
пользователями.
шине. Таким образом, виртуальные машины мы можем рас-
сматривать как перенесение принципов мультипрограммирова-
ния на самый нижний уровень операционной системы.
Рассмотрим, например, рис. 6.36. Операционная система
ОС1 — мультипрограммная, поддерживающая одновременную
работу трех пользователей; операционная система ОС2 — одпо-
программная; ОСЗ — операционная система, которая в этот мо-
мент тестируется. Есть также программа пользователя (Поль-
зовательб), предназначенная для работы в режиме супервизора
в качестве автономной программы, не находящейся под управ-
лением операционной системы.
Все три операционные систем., п ----
тель фактически работают „а одной пеа/ЛТ°"ОМ"ый "ользова.
они имеют дело не с ней, а с мп .. т Р ЬНОи машине Одна™
(МВМ), благодаря которому у каждо^поль??3^"^ ма1ш’н*
впечатление, что он работает на авто.юм.?аТеля издается
образом, в то время как обычные пользовав" машипе- Таким
традиционным способом, имеется возможней «Суживаются
вне операционные системы, а также оаТпе...^ 0Тлаживать но.
1 решить пользователям
Рис. 6.37. Виртуальная машина как расширение понятии иерархической
структуры.
в
особых случаях работать в режиме супервизора 1). Если тес-
система или автономный пользователь разрушит си-
это отразится лишь на их виртуальных машинах,
машины смогут спокойно про-
тируемая
стему, то
Другие пользователи реальной
должать свою работу. г
На рис. 6.37 показано, каким образом создается подобная
иллюзия. Программы самого нижнего уровня операционной
системы имеют дело не с реальной машиной, а с монитором
.»
” Автор идеализирует положение дел. В режиме це за-
можно отлаживать только те части операционных Спе .сгв аппара-
трагивают аппаратных управляющих регистров и / Р.
туры, используемых монитором ОС. — Прим. реи.
виртуальной. МВМГ совершенно невидимый ни операционной
системе, ни программе пользователя, предоставляет те ?ке ре*
сурсы, обслуживание и функции, что и лежащая в основе ре-
альная машина. 1
Каждый непосредственный пользователь виртуальной маши-
ны, например ОС1 или Пользователь5 на рис. 6.36, фактически
работает не в режиме супервизора, а в пользовательском ре-
жиме. Когда такой пользователь пытается выполнить привилеги-
рованную команду, такую как SIO, STI или LPS, происходит
программное прерывание. По нему управление передается мо-
нитору виртуальной машины. МВМ имитирует (с учетом вирту-
альности машины) выполнение требуемой команды, а затем
возвращает управление пользователю. Монитор виртуальной ма-
шины активизируется и по прерыванию на реальной машине
Он определяет, какая из виртуальных машин должна быть за-
действована, и производит соответствующие изменения ее со-
стояния.
Практически монитор виртуальной машины представляет со-
бой завершенную, хотя и простую, операционную систему ре-
альной машины. Другие операционные системы и автономные
пользователи виртуальной машины являются «пользователями*
реальной операционной системы (МВМ). Таким образом, мони-
тор виртуальной машины призван осуществлять все самые су-
щественные, рассмотренные нами машинно-зависимые функции.
МВМ сохраняет для каждой машины информацию о состоянии
и распределяет реальный ЦП между различными виртуальными
машинами; это не что иное, как выполнение функции планиро-
вания процессов, рассмотренной в разд. 6.2. Используя методы,
аналогичные рассмотренным выше, МВМ выделяет каждой вир-
туальной машине самостоятельную виртуальную память и не-
сколько виртуальных каналов ввода-вывода.
Наиболее очевидные преимущества виртуальных машин —
это гибкость и удобство. Чтобы удовлетворить нужды различ-
ных пользователей, одновременно могут работать разные опе-
рационные системы. В то время как производится тестирование
операционных систем или программ автономных пользователей,
машина по-прежнему остается доступной и для обычных поль-
зователей. При работе с виртуальными машинами можно до-
стичь и более высокой степени защиты, поскольку ни одна вир-
туальная машина не имеет доступа к ресурсам другой. Недо-
статком, безусловно, является значительная сложность системы,
моделирующей работу каждой виртуальной машины. Например,
если операционная система, функционирующая на виртуальноi
машине, сама использует средства виртуальной памяти, то
жет понадобиться наличие двух раздельных уровней транс. ।
ции динамических адресов. Эффективность операционной спер-
мы виртуальной машины в основном зависит от того, ско.п-^
383
операции должно моделироваться МВД a rwnnu
выполнено непосредственно на реальной может бытъ
Дальнейшее обсуждение операционных систем
машин можно наити в Дейтел [1984] и Питерсон Г19Э^ЛЬНЫХ
6.4.3. Мультипроцессорные системы
До сих пор при обсуждении операционных систем мы имели
пело с машинами, в состав которых входил один центральный
процессор (ЦП). В этом разделе будут рассмотрены некоторые
возможные пути проектирования мультипроцессорных операци-
онных систем.
Память
Рис. 6.38. Мультипроцессорные системы со слабо связанными процессорами.
Операционная система мультипроцессорной машины должна
выполнять функции, аналогичные тем, что мы рассматривали
для однопроцессорных систем. Конечно, некоторые из них могут
нуждаться в изменениях. Например, планировщик процессов мо-
жет выделить пользовательским заданиям более одного ЦП,
поэтому в активном состоянии может находиться сразу несколь-
ко процессов. Существует также ряд менее очевидных вопросов,
большинство из которых связано с организацией системы в це-
лом.
На рис. 6.38 показана простейшая форма мультипроцессор-
ной организации. Каждый процессор имеет свою собственную
память, устройства ввода-вывода и другие ресурсы. Вдобавок
на каждом процессоре функционирует его собственная опера-
ционная система. Процессоры соединяются линиями связи.
Посылка по ним запроса является единственным способом полу-
чения доступа одного процессора к ресурсам другого. Подобная
организация, часто называемая мультипроцессорной системой
со слабо связанными процессорами, очень похожа на сеть из
однопроцессорных систем. Такие системы часто используются,
если среди различных процессоров существует специализация
функций. Например, некоторые системы разделения времени
для осуществления всех деталей управления связью с термина-
лами пользователей имеют периферийный процессор. Главный
процессор выполняет всю текущую вычислительную работу,
Рис. 6.39. Мультипроцессорные системы с сильно связанными процессорами
С обработкой; а—типа главный — подчиненный и б — симметричной.
связываясь с периферийным процессором всякий раз, когда
требуется произвести обмен с терминалами. Операционная си-
стема, работающая на каждом процессоре мультипроцессорной
системы со слабо связанными процессорами, очень похожа hi
те, что мы рассматривали при обсуждении однопроцессорных
систем. Единственной действительно новой функцией является
управление сообщениями, посылаемыми по линиям связи.
Мультипроцессорные системы со слабо связанными процес-
сорами относительно просты, потому что каждый ресурс выде-
ляется какому-нибудь одному процессору. С другой стороны,
в некоторых мультипроцессорных системах допускается прям"1
распределение ресурсов между процессорами. Такая организа-
ция, называемая мультипроцессорной системой с сильно связан-
ными процессорами, отчасти усложняет задачи операциопн ж
системы.
На рис. 6.39 демонстрируются две разновидности му н _
процессорной системы с сильно связанными процессорами
рис. 6.39а показана система, реализующая принцип главным
подчиненный. Это означает, что все управление ресурс
и другими функциями операционной системы осуществляем 1
одним главным процессором. На него полностью возложим1
управление работой всех подчиненных процессоров, выполняю
щих задания пользователей. Процессоры взаимодействуют либо
непосредственно через линии связи, либо через рабочие области
совместно используемой памяти. В мультипроцессорных систе-
мах, реализованных по принципу главный — подчиненный про-
цессоры могут совместно использовать такие ресурсы' как
память и файлы данных. Однако программы и структуры тай-
ных, составляющих саму операционную систему, не' разделяют-
ся; они используются только главным процессором. Таким об-
разом, такой тип операционной системы также несколько похож
на рассмотренные нами однопроцессорные системы.
Наиболее важной проблемой в мультипроцессорных систе-
мах типа главный — подчиненный является несбалансирован-
ность использования ресурсов. Например, главный процессор
может быть перегружен запросами от служб операционной си-
стемы, и это станет причиной длительных простоев подчинен-
ных процессоров. Вдобавок любая неисправность в аппаратуре
главного процессора вызывает останов всей системы. Всего это-
го можно избежать, разрешив любому процессору выполнять
любую функцию, которая будет затребована операционной си-
стемой или программой пользователя. Этот подход, называемый
симметричной обработкой (иногда используется термин «распре-
деленная ОС».— Род.), демонстрируется на рис. G.396. С его
помощью ликвидируются потенциально слабые места в системе
типа главный — подчиненный, так как все процессоры имеют
возможность выполнять один и тот же набор функций. Вдо-
бавок неисправность одного процессора не обязательно вызо-
вет выход из строя всей системы. Остальные процессоры могут
продолжить выполнение всех необходимых функций.
В симметричных мультипроцессорных системах различные
части операционной системы могут выполняться одновременно
разными процессорами. Из-за этого разработка подобных си-
стем может оказаться значительно сложнее и труднее по срав-
нению с рассмотренными выше. Например, все процессоры дол-
жны иметь доступ ко всем структурам данных 1), используемым
операционной системой. Однако процессоры имеют дело с этими
структурами данных независимо друг от друга, и, если два
процессора одновременно пытаются изменить одну и ту же
структуру, могут возникнуть осложнения (см. разд. 6.3.3). Сим-
метричные мультипроцессорные системы должны иметь сред-
ства, с помощью которых осуществляется управление доступом
к структурам данных и к критическим таблицам операционной
системы. Для решения этой задачи не достаточно операции за
проса и отказа, рассмотренных в разд. 6.3.3, так как л
Под структурами данных здесь имеются в ни,о <1 ait.iri,
И т. п. — Прим. ред.
различных процессора могут выполнить операции запроса одно-
временно. Поэтому обычно требуется, чтобы аппаратура обта-
дала особыми свойствами, позволяющими одному процессору
захватывать управление критическим ресурсом, 'блокируя на
один шаг все другие процессоры. Обсуждение подобных сре^
ств можно найти в Питерсон [1983] и Лорин [1981]. н
Дальнейшую информацию по операционным системам для
мультипроцессоров можно найти в Дейтел [1984], Лопин 119811
и Мэдник [1974]. и 1 1
6.5. Примеры реализаций
В этом разделе дается описание нескольких реально сущест-
вующих операционных систем, специально выбранных для того,
чтобы продемонстрировать разнообразие в разработке и приме-
нении программного обеспечения такого рода. Как и в преды-
дущих примерах, в наши задачи не входит дать полное и по-
дробное описание каждой системы. Вместо этого мы выделим
некоторые присущие им наиболее интересные или часто встре-
чающиеся свойства, а для читателей, желающих получить боль-
шую информацию, дадим ссылки на соответствующую литера-
туру.
Первые два примера — операционные системы, не привязан-
ные к какой-нибудь одной машине. В разд. 6.5.1 рассматрива-
ется небольшая переносимая однопользовательская система
UCSD Pascal, функционирующая на мини-ЭВМ. В разд. 6.5.2
описывается UNIX, более сложная операционная система, кото-
рая также может быть реализована и на разных ЭВМ.
Другие примеры — системы, разработанные для определен-
ных семейств ЭВМ. Разд. 6.5.3 посвящен NOS™, функционирую-
щей на ЭВМ серии CDC CYBER; это пример мультипроцессор-
ной операционной системы. В разд. 6.5.4 рассматривается систе-
ма VAX/VMS™, в которой используются некоторые интерес-
ные методы управления виртуальной памятью. В разд. 6.5.5
рассматривается VM/370 фирмы IBM, операционная системе,
на базе которой могут быть реализованы многочисленные вир-
туальные машины.
6.5.1. Система UCSD Pascal
Система UCSD Pascal
— это операционная система для м»1'
ни-ЭВМ. Написана она почти целиком на языке Паскаль п
функционирует на псевдо-машине, или P-машине (разд.
и 5.5.2). Таким образом, она может работать на любой /)Ь . '
где реализован соответствующий интерпретатор. Сама по
система UCSD Pascal относительно проста. Поскольку
предназначена для поддержания работы одного пользователя
на мини-ЭВМ, для ее реализации не требуется применения
сложных средств.
Одной из наиболее интересных частей системы UCSD Pas-
cal является ее интерфейс с пользователями, имеющий древо-
видную структуру. На каждом уровне дерева системой выда-
ется строка-подсказка (prompt line), часто называемая меню
[(menu). Она содержит список команд, которые может ввести
пользователь. По каждой из них выбирается соответствующая
ветвь, и пользователь переводится на более низкий уровень де-
рева. Затем выдается новая строка-подсказка, содержащая
команды, которые можно ввести уже на этом уровне. На самом
нижнем уровне система запрашивает у пользователя при необ-
ходимости дополнительную информацию и выполняет команду.
Например, когда система загружена впервые, ею выдается
строка-подсказка вида
Команды: E(dit,R(un,F(ile,C(omp,L(ink,X(ecute,A(ssem,D(ebug.
По команде Е пользователь переводится на один уровень
ниже и попадает в Редактор (Editor), где выдается новая
строка-подсказка. Она может иметь вид
Редактор: A(djst,C(py,D(lete,F(ind,I(nsrt,J(mp,R(epIacc,
Q(uit,X(chng,Z(ap.
(Реальные строки-подсказки в зависимости от версий системы
могут немного различаться.) По команде I система запрашива-
ет у пользователя вводимый текст. По команде Q пользователь
выходит из Редактора и возвращается к корню дерева (на-
чальной строке-подсказке.)
На самом внешнем уровне имеющиеся команды обеспечива-
ют простой доступ к наиболее важным функциям системы.
Редактор позволяет пользователю ввести текст и отредактиро-
вать любой заданный текстовой или системный рабочий файл.
'В программе Файлер имеются команды для управления файла-
ми на диске. Это, например, команды выдачи справочной ин-
формации, копирования и создания новых файлов. Компиля-
тор, ассемблер и Редактор связей — это системные пршра.ммы,
выполняющие функции, аналогичные тем, что были рассмотри
По команде R(un внешнего уровня система начинает '
полнение программы из текущего рабочего файла. о - '
система запрашивает имя файла и выполняет содержа . -
нем программу. По D(ebug программа из тек}-щего Ф3*1'
полняется под управлением системного Отладчик , РЦ1
вызывается в случае появления ошибки или по /
контрольной точки, заданной пользователем.
В системе имеется также ряд вспомогательных программ.
К ним относятся, например, такие, посредством которых произ-
водится настройка системы на конкретную аппаратную конфи-
гурацию, создаются самозагружающиеся программы, выполня-
ются операции форматирования диска, не предусмотренные в
Файлере. Вспомогательные программы запускаются иа внеш-
нем уровне при помощи команды X(ecute. Операционной си-
стемой UCSD Pascal программы пользователей обеспечиваются
набором лишь основных сервисных функций. В соответствии с
нуждами программ, написанных на Паскале, в системе реали-
зовано динамическое распределение памяти; тем самым имеется
возможность в случае надобности переназначить содержимое
основной памяти. Поддержка параллельности работы мини-
мальна. Большая часть активности системы, включая операции
ввода-вывода, синхронизована. Э го означает, например, что опе-
рация READ приводит к тому, что программе пользователя
приходится ждать завершения физической операции ввода-вы-
вода; в это время ни одно другое задание не может быть вы-
полнено. Дальнейшую информацию по системе UCSD Pascal
можно найти в SofTech Microsystems [1980 и 1983J.
6.5.2. UNIX’)
Операционная система UNIX первоначально была разраб -
тана в Bell Laboratories для семейства ЭВМ DEC PDP-11.
С тех пор она была реализована на многих других машинах,
от больших ЭВМ до микропроцессоров. Сейчас существует не-
сколько версий UNIX. Ниже будут рассмотрены некоторые при-
сущие всем им наиболее интересные свойства системы.
Интерфейс пользователя в системе UNIX реализован нр<
граммов, называемой оболочкой (shell). Эго интерпрета к>.
командных строк, воспринимающий строки, вводимые пользой;,
телем, в качестве запросов па выполнение других программ
Сначала по каждой команде вызывается соответствующая пр
грамма. По ее окончании оболочка также завершает работу и
ожидает от пользователя следующую команду. Или же об
ломка может запросить команду сразу после запуска требуемо!
программы, нс дожидаясь ее завершения. В функции оболом!
входят также замена параметров, выполнение команд, основан-
ных на сравнении символьных строк, а также передача управ-
ления в пределах последовательности команд.
Стандартная оболочка, рассмотренная выше, предназначен
для того, чтобы предоставить пользователю доступ ко всем воз-
*> По работе D. М. Ritchie and К. Thompson «The -V
System». Communications of the ACM, Vol. 17, No. 7. I I . t
sociation for Computing Machinery, Inc.
можностям системы UNIX. Иногда .
смотреть особый интерфейс пользователя что “ож^п "л "реду’
стичь, применив нестандартный вариант 'оболочки Й™
разделе файла ‘паролей. Эта ‘.рог^аX °Х7„МЬСКОМ
ьать команды таким образом, чтобы обеспечивай я РпРетиР0<
приспособленный к требованиям особого пользователяТН?п?и’
мер, для пользователей системы секретарского редактиповаТя
• • задано, чтобы вместо
стандартной оболочки была использована программа редакХп
вания текстов. Таким образом, пользователи могуг начать па’-
боту сразу же после входа в систему. Оболочка может помочь
и в обеспечении защиты системы: пользователям индивидуаль-
ной командной оболочки может быть запрещено вызывать'не
предусмотренные для них программы системы UNIX
В системе UNIX процессам разрешено создавать другие про-
цсссы, независимо претендующие на системные ресурсы. Сие-
темный вызов fork приводит к разбиению процесса па два
выполняющихся независимо: родительский процесс и порожден-
ный процесс. В UNIX имеются средства, обеспечивающие син-
хронизацию процессов, при помощи которых родительский про-
цесс может ожидать завершения работы порожденного процес-
са, а также получать информацию о его состоянии.
Процессы в UNIX могут связываться непосредственно друг
с другом через логические межпроцессные каналы, называемые
транспортерами (pipes). Для передачи сообщений между про-
цессами используются обыкновенные запросы на чтение и
запись. Ни процессу, ни тем более простому файлу нс требует-
ся знать, что в этом принимают участие транспортеры. Синхро-
низация процессов и буферизация сообщений автоматически
обрабатываются системой. Несколько процессов при помощи
транспортеров могут связываться в линейную структуру и обра-
зовывать конвейер (pipeline), в котором выход одного процесса
является входом другого.
UNIX поддерживает иерархическую файловую систему. Для
файлов пользователя имеются каталоги с древовидной щрукп-
рой; система тоже имеет несколько каталогов для своих и)жд.
Один и тот же файл может фигурировать в ^скольких разд и-
ных каталогах, возможно, и под разными именами с 4
файлы имеют одинаковый статус. Иными слова _,Ф
принадлежит какому-то одному определенном)
лы могут быть и не включены ни в один каталог.
Самое необычное свойство Фай^в0,‘^,С^Гктв ввода-
шествование специальных фа»™* К^д вует п0 крайней
вывода, поддерживаемому UNIX,1/°°Хь. читаются и пишут-
мере один такой файл. Специальные ф “ диске, Однако
ся так же, как и обычные, содержащиеся на диске, д
запрос на чтение и запись специальных файлов вызывает запуск
соответствующего устройства. Это делает файлы ввода-вывода
и устройства ввода-вывода очень похожими. Например, устрой-
ства являются объекюм того же самого механизма защиты
что и обычные файлы.
Дальнейшую информацию и ссылки, касающиеся системы
UNEK, МОЖН° НаЙ™ В Баури 11983Ь Дейтел [1984) и ритчи
6.5.3. NOS
NOS — операционная система, предназначенная для исполь-
зования на ЭВМ серии CDC CYBER и 6000. Это мультипро-
цессорные машины, имеющие одни или два центральных про-
цессора (ЦП) и до 20 периферийных процессоров (ПП). ЦП и
ПП работают с общей центральной памятью; таким образом,
NOS является примером мультипроцессорной системы с сильно
связанными процессорами. Однако к каналам и устройствам
ввода-вывода ЦП не имеет прямого доступа. Этот доступ обес-
печивается периферийными процессорами. Используя специаль-
ные аппаратные команды, ПП могут запускать и останавли-
вать ЦП.
Под управлением NOS ЦП используется практически только
для выполнения программ пользователей. ПП осуществляют
ввод-вывод и большую часть функций операционной системы;
однако определенная системная работа, если это может быть
сделано с большей эффективностью, выполняется на ЦП. Каж-
дому ПП в центральной памяти отведен блок из восьми слов,
через который осуществляется связь с системой.
Все управление машиной возложено на системный монитор,
состоящий из программ MTR на ПП и CPUMTR на ЦП. МП<
непрерывно сканирует запросы на обслуживание заданий по.ть-
зователей. Подробно об этом будет рассказано ниже. CPIMIK
назначает периферийным процессорам задания, по одному па
каждого. Когда задание завершается, ПП оповещает систему.
Этого ждет CPUMTR, прежде чем назначить ПП следующее
задание.
Каждому заданию пользователя в центральной памяти
ведена определенная область. Машины, на которых функцио-
нирует NOS, имеют аппаратно реализованные регистры пере-
мещений, аналогичные тем, что были рассмотрены в разд 6.- - -
поэтому существует возможность перемещать задания во время
их выполнения. NOS получает от этого двойное преимушсс'1'1”
Во-первых, заданиям разрешается через запросы на обслужи
ванне операционной системе увеличивать или уменьшать ко.н’
чество выделенной им центральной памяти. Чтобы удовлеи”'
рить эти запросы, NOS перераспределяет содержимое центра.11.
ной памяти. Во-вторых, NOS может временно приостановить
выполнение некоторого задания с тем, чтобы сделать централь-
ную память доступной процессу с более высоким приоритетом
Это называется свертыванием задания. Когда же задание вновь
будет развернуто и продолжит выполнение, то не обязательно
чтобы оно размещалось в той же самой области центральной
памяти, что и раньше.
Первые 64 слова области памяти, выделенной заданию за-
резервированы под связь с операционной системой. Чтобы осу-
ществить запрос на обслуживание операционной системе, про-
грамма пользователя заносит его код в фиксированное место
области связи. Программа MTR периферийного процессора не-
прерывно сканирует эти области, проверяя наличие кода запро-
са. Когда он обнаружен, MTR активизирует CPUMTR для того,
чтобы тот назначил ПП для запрашиваемого действия.
Средства, используемые NOS для синхронизации выполнения
программ и сервисных функций, несколько отличны от тех, что
были рассмотрены в разд. 6.2.2 и 6.2.3. Программа пользова-
теля, запрашивающая услуги операционной системы, может по-
требовать, чтобы ее временно перевели в состояние блокировки.
Когда сервисная функция завершится, программа снова акти-
визируется. В NOS это называется автоматическим перевызо-
вом. Такое свойство часто используется, например, при ожида-
нии завершения затребованной операции ввода-вывода.
Если программа желает продолжать работу во время выпол-
нения сервисной функции, то опа запрашивает функцию без за-
каза автоматического перевызова. Если программа должна
ждать завершения затребованного сервиса, то она делает спе-
циальный запрос на периодический псревызов, в результате
чего она на некоторое время переводится в заблокированное
состояние. По истечении этого времени программа снова акти-
визируется и проверяет, может ли она продолжить работу или
нет. Если сервисная функция еще не завершена, то программа
вновь делает запрос на периодический перевызов. Аналогичный
технический прием может быть использован для осуществления
нескольких запросов на обслуживание, например одновремен-
ного выполнения несвязанных друг с другом операций ввода-
вывода. . „
Дополнительную информацию по NOS можно наити в оио
{[1981 и 1983].
6.5.4. VAX/VMS
VAX/VMS —это многоцелевая операционная система пред
назначенная для использования на ЭВМ серии \ А. •
управлением можно работать в трех режимах: па'ч<^ ’ ’ '1О
деления времени и реального времени. Неотъемле.
использован, она может быть перевызвана без выполнения
зического ввода-вывода. пии <ри-
Другая программа операционной системы, называемая swnn
per, используется для перемещения в память и из нее паЛпХ
множеств целых процессов. Задача swapper — держать в nJ
ти активные процессы с наивысшим приоритетом чтобы пт
могли участвовать в планировании. Таким образом <Ьуик
swapper аналогичны тем, что выполняет планировщик пооме
жуточного уровня, упоминавшийся в разд. 6 3 2
Функция планирования процессов в VAX/VMS основана на
32-уровневой системе приоритетов. Нижние 16 уровнен зарезеп
вированы для обычных процессов; остальные — для процессов
реального времени. Каждый процесс в системе определен бло-
ком управления процесса и своим заголовком. Блок управле-
ния процесса содержит кластеры флагов событий, которые мо-
гут быть использованы процессами для связи и координации
их действий.
Для синхронизации взаимодействующих процессов при ис-
пользовании ими разделяемых ресурсов в VAX/VMS имеются
средства блокировки. Существует шесть различных режимов
блокировки, каждый из которых обеспечивает свой уровень
разделения.
Поддержка операций ввода-вывода осуществляется двумя
уровнями: службой организации ведения записей (СОВЗ) и си-
стемным сервисом ввода-вывода. Процедуры СОВЗ реализуют
независимый от устройств файлово-структурированный доступ к
устройствам ввода-вывода. Такие функции, как блокирование
записей, могут быть выполнены либо СОВЗ, либо пользовате-
лем. Обслуживание, зависящее и не зависящее от устройств,
обеспечивается системным сервисом ввода-вывода. Пользовате-
ли с достаточными привилегиями для задания своих файловых
структур могут выполнять прямые операции ввода-вывода на
персональных дисковых или ленточных устройствах. Оба типа
поддержки ввода-вывода для создания очереден и выполнения
физических операций ввода-вывода используют одни и те же
системные программы более низкого уровня.
Дальнейшую информацию по VAX/VMS 1.
можно найти в Дей-
тел |1984] и DEC | 982].
6.5.5. VM/370 °
VM/370 — операционная система для
живающая работу многих виртуальных
IBM 370, поддер-
машин. Каждому
» Из «VM/370 —A Study of Multiplicity and sefi 1 > copyright
weight and R. A. MacKinnon, IBM Systems Journal, Vol,
197‘J International Business Machines Corporation,
Приложение В
Справочный материал по УУМ/ДС
Структура слова состояния
Разряды Имя Использование поля
0 1 2-5 6-7 8-11 12-15 16-23 ин гЕ Л " реж,1м пользователя-. 1 = оеж1,„ rvnn„ IDLE 0 = активен; 1 = пассивен Р с>первтора Идентификатор процесса аЛстл 14°А УСЛ0В,1Я MASK Маска прерываний тгппг 1,е используются lUUDb Код прерывания
Прерывания
Тип
Класс прерывания
I SVC
И Программное
III По таймеру
IV По вводу-выводу
Адрес
рабочей
области Код прерывания
(шестнадцатеричный)
100 Код команды SVC
130 Причина (см. ниже)
160 Нет
190 Номер канала
Коды команды SVC
Мнемоническое иепез регистры
Код имя Параметры, передаваемые через per ----
0 WAIT
1 SIGNAL
2 I/O
/А) = адрес ESB для события
(Д1__ятрес ESB для события
(А) = адрес канальной программы
„оме? даераци обмена
3 REQUEST
4 RELEASE
(Т) = адрес имени РесУ£®
(Т) = адрес имени ресурс
пользователю кажется, что он имеет дело с самой System/370
включая и каналы ввода-вывода.
Система VM/370 состоит из двух основных компонентов:
'У^\сиу'г1.Р.оеРал1МЬ1 (УП) и диалоговой мониторной систе-
’ является распорядителем ресурсов системы
и выполняет те же функции, что и мониторы визуальных ма
шин, рассмотренные в разд. 6.4.2. В УП также имеются коман-
ды, помогающие в управлении и отладке операционной системы
на виртуальной машине. Они позволяют выполнять такие дей-
ствия, как чтение содержимого виртуальной памяти и установка
контрольных точек. В сущности, это те же отладочные функции
которые системным программист может выполнить на пул.™
реального ЦП. иа пультс
На виртуальных машинах под управлением УП могут функ-
ционировать все операционные системы, обычно используемые
на ЭВМ серии 370. Включая, конечно, и саму УП. Возможность
выполнения УП на виртуальной машине под управлением дру-
гой УП делает возможной поддержку виртуального окружения
VM/370. Это особенно полезно при отладке частей УП или
постановке новых версий УП в системе.
Диалоговый монитор системы (ДМС) обеспечивает интер-
активную поддержку единственного пользователя на одном тер-
минале. Работа со многими терминалами осуществляется бла-
годаря тому, что УП имеют возможность поддерживать функ-
ционирование многих виртуальных машин с ДМС на кажд<>й
из них. ДМС разработан специально для VM/370 и в своей
работе прямо зависит от УП. В отличии от других операцией
ных систем для IBM 370 функционировать самостоятельно на
реальной машине он не может. Однако под управлением Ml
ДМС работает эффективнее, чем другие системы.
Можно сказать, что ДМС предоставляет своим пользован
лям дружественный интерфейс. Он состоит скорее из набора
команд, ориентированных на пользователя, чем из набора опе-
раторов для управления заданиями, как это имеет место в др'
гих операционных системах серии 370. О самой операционно
системе помимо того, что необходимо для выполнения требу -
мой функции, пользователю нужно знать сравнительно ч'1
Когда имеешь дело с использованием операционных спек >.
поддерживающих работу виртуальных машин, приходится i р
нимать во внимание производительность всей системы. Из.ар-
ки, возникающие в результате функционирования монин
виртуальной машины, обычно уменьшают пропускную споуЯ’.
ность системы и увеличивают время ответа. В VM/3/0 н\
ся средства измерения производительности, с помощью koi-p
во время выполнения УП можно получить информацию об
пользовании ресурсов, а также осуществить сбор резульы<
измерений для дальнейшего анализа.
ЛЫ
Существует также несколько способов -----
дительности системы. Например, заданныеел"чения проИЗво.
быть заблокированы в реальной памяти""Ы® стр.а»»цы могут
-закреплены за определенной внр^альУноТИСТВа Н кана’
кая-либо виртуальная машина может функции маши«°й- Ка-
ме виртуальныи-как-реальный. В этом елч-чао п"ровать в Рыжи-
ной машины не участвует в осуществляемом „ ять В11Ртуаль-
УП размещении страниц по запросу. М под упРавлением
Другие усовершенствования в noornxwun. г
лее специфичны к подразумевают изменения в^опепю.'"'" б"‘
системах, на которых реализовано виртуальное
изменения позволяют операционной XХрХХ Эт"
шины узнать, что она работает под управлёнЕ VMmn
связаться непосредственно с УП. Тем с!мым система нУ
на больше выполнять операции, которые при ее ваботе и»
туальной машине были бы излишни. Эти изменении пёзывае
мые в совокупности рукопожатием, повышают эффектавпость к
увеличивают производительность виртуальной машин и
В определенных моделях System/370 и соответствующих
процессорах имеются специальные средства, предназначенные
для использования с VM/370. Они позволяют аппаратно управ-
лять некоторыми наиболее часто выполняемыми УП функция-
ми. В результате достигается значительное увеличение произво-
дительности виртуальной машины.
Дальнейшую информацию по VM/370 и соответствующие
ссылки можно найти в Дейтел [1984] и Спрайт [1979]. '
Упражнения
Раздел 6 2
1. В разд. 6.2.1 мы предполагали, что если происходит какое-то пре-
рывание, то все другие прерывания равного или более ' ,^способной,
запрещаются. Будет ли схема, рассмотренная в те ? , ]
если мы просто запретим все прерывания того же класса.
2. Предположим, что обработка прерываний опредс *"сего вре.
обычайно сложна. Может оказаться нежелательным поедлоЖ11Те метод
меня обработки оставлять другие прерывания закр • рем'е1Ш прерыва-
обслуживания прерываний, при котором большую часть времени 1
НИЯ могут оставаться открытыми. „„опипяний
3. В чем преимущества существования‘ "^|f^Ilj^"aCC’^I ,npepbiBairiiH осу-
по сравнению с одним, при котором индикация классг l
ществляется при помощи флагового бига. чпВателЯ на ПП
4. Предположим, что время работы разных*заданий различна. Какая
ограничено. Его предельная величина д. ' Р'' тем Чтобы лимит врем
часть операционной системы должна следит , за
не был превышен, и как это может >ы - • йП₽пллится в состояние
б. На УУМ/ДС У'та»ов'<»« ,С)1-Дз°ожтсть была рм.1113<»«“а “а
б. Предположим, вы хотите создать мультипрограммную операционную
систему, поддерживающую пакетный режим работы на ЭВМ, не имеющей
мшервального таймера. Какие возникнут проблемы? Можете ли вы приду-
мать способ их решения с использованием каких-нибудь других средств,
реализованных как аппаратно, так и программно?
7. Как вы ответите на вопросы упр. 6, если операционная система под-
держивает еще и работу в режиме реального времени?
8. Рассмотрим мультипрограммную операционную систему. Предполо-
жим, что в течение какого-то времени только одно задание пользователя
находи гея в состоянии jotobhocth и .может выполняться на ЦП. По исте-
чении оIводимого ему кванта времени оно будет периодически прерываться.
При этом диспетчер только что сохраненное состояние задания будет сразу
же восстанавливать, а само задание активизировать, предоставляя ему еще
одни квант времени. Как можно избежать ненужных издержек такою
рода, если считать, что операционная система по-прежнему может обслужи-
вать и другие задания, как только они приходят в состояние готовности?
9. Вместо одного списка всех заданий с информацией об их состоянии
в некоторых системах существует несколько списков (т. е. список готовых
заданий, список блокированных заданий и т. д.). Каковы преимущества и
недостатки такого подхода?
10. В примере на рис. 6.15 считалось, что прерывания по таймеру от-
сутствуют. Предположим, что квант времени, назначенный процессу PI,
истекает в интервале между моментами (2) и (3). Перерисуйте диаграмм
до момента (10) так, чтобы были отображены все возможные последов
цельности событий, которые могут произойти после прерывания по таймеру.
11. Перерисуйте диаграмму на рис. 6.15 с учетом того, что процесс 1’2
имеет более высокий приоритет диспетчеризации, чем процесс Р1, и ч, >
используется приоритетное планирование процессов.
12. Предположим, что в мультипрограммном режиме выполняются л .
задания. Задание А много времени расходует на выполнение па ЦП и
мало — на ввод-вывод. Задание В занимает мало времени ЦН, а операции
Ввода-вывода осуществляет много. Какому из этих заданий следует и
своить больший приоритет диспетчеризации для увеличения производите •
кости всей системы?
13. Предположим, что супервизор ввода-вывода имеет возможность
бирать запросы из очереди к каналу, основанной на системе npnopniei
Какому из двух заданий упр. 12 следует дать в этом случае бо.п.
приоритет на ввод-вывод?
14. Предположим, что к некоторому устройству ввода-вывода
получить доступ через любой из двух каналов ввода-вывода, однако к;ь
раз оно может быть использовано только одним каналом. Как с ук-.
этого нужно изменить рассмотренные нами программы супервизора вв
вывода?
15. Какие вы выберете число и размер разделов для системы уч
Вия памятью с разделами фиксированного размера?
16. Какие преимущества и недостатки имеет подход к защите П1 ' ,
С использованием граничных регистров по сравнению с защитой по клю
17. Часто в мультипрограммной системе операция ввода-вывода
одного задания выполняется в то время, пока другое работает на П11
обеспечить защиту памяти для такой операции ввода-вывода? Как, 1|(
мер, можно предотвратить чтение данных одним заданием из раздела
пых другого?
Упражнения
397
18. Предположим, что в неклтппг^ ' —
при помощи которых отражается тип каждого да.жоГ флаговыв биты,
памяти или регистре (например, целый, снмвотыи!й ’ сохРаняемо?0 в
точкой, команда, адрес). Как эта информация м“‘’’Ч,'СЛ0 с «-«вающей
для реализации в машине перемещаемых разделов?”0114” Сигь «пользована
19. Нужны ли аппаратные средства зашит.. „
управление памятью осуществляется при пома ... яг" "я машине, где
запросу? Р“ ПОМО,ВД размещения страниц по
20. Нужен я., на машине из упр. ,9 перемешаемый за ,
21. Некоторые системы с оазметенил..
ЛЯЮТ выбор страниц для выталкивания из памяти* нсходяРизУтоп * г"”’
модифицирована страница или пет. То есть систем’, п.™?,? °' была
путь ту страницу, которая с моментаi не бХ м ВЬ'Т”ЛК*
Какие преимущества н недостатки у этого подхода? ‘ модифицирована.
22. Какие методы может использовать программист для увеличения то
калыюсти ссылок в программе? Какие технические приемы' Z Хшо-
вання и какие структуры данных могут привести к ухудшению лока'шюстн
ССЫЛОК г
23. Как будет выглядеть диаграмма на рис. 6.266 для программы
которой отсутствует локальность ссылок (т. е. программа, и которой каж\о«
обращение к памяти не зависит от предыдущего)? Как будет выглядеть'
диаграмма для программы с идеальной локальностью ссылок (т. е. та,
у которой каждое обращение осуществляется к тон же странице, что и
предыдущее)?
24. В мультипрограммной системе в то время как одно задание ожи-
дает завершения операции ввода-вывода, другие могут выполнять полезную
работу. Почему тогда пробуксовка одной программы в системе с виртуаль-
ной памятью создает проблемы и для других программ?
25. Придумайте алгоритмы работы обработчиков прерываний четырех
уровней в мультипрограммной операционной системе с размещением страниц
по запросу, работающей на УУМ/ДС.
26. Почему у прерываний по таймеру более низкий приоритет на
УУМ/ДС, чем у SVC-прерываний (см. разд. 6.2.1)?
27. Почему прерывание по вводу-выводу имеют более низкий приоритет
на УУМ/ДС, чем SVC-прерывания?
Раздел 6.3
1. Придумайте алгоритм работы программы УГ1Ра[’;^11И>' "^р|?рус.м’'|ло
торая выполняет операции блокирования и бхферь-^ ,
на рис. 6.28. г жойлпч
2. Когда может быть выгодно при работе с последовательным
использовать более двух буферов? „ логичную приведен-
3. Нарисуйте диаграмму изменения состоят’ Иия, показанной
. 6.7, для трехуровневой процедуры пла н
ной на рис
на рис. 6.296.
4. Может ли
быть, чтобы время "Р^щ^'врсмаш^его прохождения
граммной операционной системе был- ?
в одионрограммной системе на тон м ; программ опера-
5. Опишите алгоритмы "и отказа. рассмотреть
ционной системы, реализующие ] у
в разд. 6.3.3.
6. Предположим, что в системе блок состояния событий для каждого
ресурса определен таким образом, что «событие наступило» эквивате.ино
в логическом смысле «ресурс свободен». Могут ли функции запросиот
смотреХ'"ш?С использова‘“'™ операций WAIT п SIGNAL, рас-
пользования операций запросами"отказ^мы"'^^- "t? Р"С’ 6'31’ Вмссто нс*
но таймеру в промежутке между стпоктм^оа запРетить прерывание
ками 37 и 40 программы Р2. (Прерывания И “г пР0ГРаммы Р' и стро-
при помощи запросов на обслуживание ппг^°ГУТ бЫ-Ь закРыты п открыты
это быть практическим решением проб тем ii Pn^°HH°H системе ) Может ли
„ „ “роолемы, рассмотренной в тексте?
8. Как операционная система может определить «тп ,
блокировка? д 1ть> что произошла взанмо-
Глава 7. Другие компоненты системного
программного обеспечения
В этой главе мы вкратце пасгилтпим
лоненты системного программного обеспечен,,я₽“ашГц'яь'"
внести связанные с „ими основные понятия „ определения 1ь
скольку объем книги ограничен, мы не стремимся мть дета ь‘
ное описание их реализаций. А для читателей яюХ
глубже изучить эти вопросы, в конце каждого раздма Пиии„-
дены ссылки на соответствующую литературу. рИ е
Раздел 7.1 посвящен описанию задач и функций обобщенных
систем управления базами данных (СУДЕ) и их взаимодей-
ствию с операционными системами. В разд. 7.2 дается кпа'ткое
описание диалоговых систем редактирования текстов, обсужда-
ются заложенные в них основные идеи.
В разд. 7.3 рассматриваются системы интерактивной отладки
программ. Хотя потребность в таких системах уже давно изве-
стна, практически их существует сравнительно’ мало. Поэтому
в разд. 7.3 внимание уделяется тем функциям и характеристи-
кам, которые в дальнейшем развитии программного обеспече-
ния такого рода, возможно, окажутся наиболее существенными
7.1. Системы управления базами данных
В этом разделе будут рассмотрены основные задачи и функ-
ции обобщенной системы управления базами данных (СУБД).
СУБД нас будет интересовать главным образом с точки зрения
пользователя. Мы рассмотрим также, как связаны между собой
СУБД и другие компоненты программного обеспечения системы.
Сравнительный анализ теоретических и практических реали-
заций системы управления базами данных можно найти у
Уидерхолда [1983], Дейта [1981], Ульмана [1980] и других
авторов.
В разд. 7.1.1 обсуждаются проблемы, решение которых при-
вело к созданию систем управления базами данных, а также
вводится понятие СУБД. В разд. 7.1.2 в общих чертах расска-
зывается о том, что представляют собой эти системы с точки
зрения пользователя. В разд. 7.1.3 рассматривается вопрос
о связи СУБД с другими компонентами системного про-
граммного обеспечения, в особенности с операционными
системами.
7.1.1. Основные концепции СУБД
Разработка систем управления базами данных в большой
степени явилась результатом решения двух основных проблем,
возникших при работе с обычными системами файловой обра-
ботки: избыточности и зависимости данных. Рассмотрим, напри-
мер, рис. 7.1, на котором показаны в упрошенном виде несколь-
ко систем файловой обработки для некоего гипотетического
университета. Сюда входят: система регистрации, позволяющая
следить за составом студентов на курсах, система финансовой
помощи, контролирующая расход стипендиального фонда, си-
стема платежных ведомостей для всего университета, включая
профессорско-преподавательский состав и студентов, работаю-
щих по найму.
Рис. 7.1. Раздельные системы файловой обработки.
Каждая система файловой обработки состоит из ряда про-
грамм и набора файлов данных. Формат, организация и содер-
жимое последних задаются тем, кто с самого начала определяет
систему. В файлах каждой системы содержится только не-
обходимая ей информация. Согласование между файлами раз-
личных систем либо незначительно, либо вовсе отсутствует.
Использование автономных систем файловой обработки,
аналогичных тем, что показаны на рис. 7.1, часто приводит к
значительной избыточности данных, т. е. к дублированию эле-
ментов данных в различных файлах. Например, число курсов
на которых числится студент, может храниться как в одном из
файлов системы регистрации, так и в файле системы финан-
совой помощи. Л если к тому же студент работает в универси-
тете по найму или получает стипендию, то его фамилия и а
рес могут появиться в трех различных местах.
Наиболее очевидным недостатком избыточности данных
является необходимость использования дополнительной памяти.
Однако существуют и более серьезные проблемы, связанные с
дублированием данных. При изменении информации, если сны
«ранится в нескольких местах, исправления должны быть сде-
ланы несколько раз. Для этого требуется больше машинною
6
ис. 7.2. Зависимые от данных программы, использующие ооъединспиую
азу данных. (1о, что требует изменения при добавлении новой системы,
заштриховано.)
времени и операций ввода-вывода. Но еще серьезнее то, что
существует вероятность несоответствия данных из-за ошибок в
программе или различия в планировании при изменении фай-
лов. Например, запись в файле регистрации может отражать
тот факт, что некоторый студент отчислен с определенного кур-
са; однако эта информация может быть не занесена в cooibci-
ствующие файлы системы финансовой поддержки.
Одно из возможных решений проблемы избыточноеги пока
«ано на рис. 7.2а. Информация для всех файловых систем
собрана в объединенную базу данных для всег0 Уипве^'1^' ‘ ’
В ней может содержаться только одна копия каждого . <~
ского элемента данных, поэтому избыточность иск.
Сама база данных состоит из набора файлов. Каждый из них
может использоваться различными прикладными программами,
которым требуется один и тот же элемент данных.
Хотя только что описанный подход решает проблему избы-
точности данных, он может спровоцировать и другие трудности.
Прикладные программы, имеющие дело непосредственно с фи-
зическими устройствами, зависят от данных. Речь идет об их
зависимости от таких характеристик, как формат записи, ор-
ганизация файла и порядок следования. При изменении харак-
теристик приходится модифицировать и прикладные программы
Предположим, например, что к прикладным программам до-
бавляется студенческая консультационная система. Ей может
понадобиться определенная информация, отсутствующая в базе
данных; следовательно, возникнет необходимость создания оч-
ного или нескольких новых файлов. С другой стороны, часть
нужной информации уже имеется. Системе могут потребоваться
такие элементы данных, как шифр специализации студента или
сведения о текущем составе студентов данного курса.
К сожалению, имеющаяся информация может быть пред-
ставлена не в том виде, какой требуется новой системе. Пред-
положим, например, что консультационная система должна
обеспечить интерактивный доступ к информации о списке ci -
дентов, имеющих определенного научного руководителя. Д. i
этого требуется, чтобы к регистрационной информации о сту-
денте была добавлена фамилия его научного руководителя, i
регистрационные данные—индексированы фамилией руководи-
теля. В результате должны быть изменены содержимое и ор-
ганизация некоторых существующих файлов. Из-за зависимое;
данных все программы, в которых эти файлы использую; с;:,
также должны быть откорректированы.
Рассмотренный случай иллюстрируется рис. 7.26. Спрае
пая система использует три файла из базы данных — один ж -
вый и два уже существующих. Необходимо изменить форма;
структуру одного из существующих файлов, используемых н<
системой (на рисунке он заштрихован). Следовательно, всей •
граммы, работающие с этим файлом, должны быть откоррс;л -
рованы. В данном случае изменения коснутся программ в с.
стемах регистрации и финансовой помощи.
Решить только что рассмотренные проблемы можно, сдслас
так, чтобы прикладные программы не зависели от таких дет
лей, как организация файлов и формат записей. Как это можь
сделать, показано на рис. 7.3а. Программы пользователей имей i
дело не с самими файлами из базы даных, а делают запрос1!
системе управления базой данных (СУБД) на логическом уро '
не без учета того, как данные хранятся в файле. Напрпж ’•
программа может запросить текущую регистрационную ши!' 1
мацию по определенному студенту. Посредством обращения д
403
г
Программы
Регистрация
База
данных
Физический
ввод-вывод
Финансовая
помощь
г—'
Консульта-
ционная
система
Платежные
ведомости
I
(Описание/:'
отображения^
б
Рис. 7.3. Не зависимые от данных программы, ' „рн И"абавл?нин 'новой
ления базами данных. (То, что требует изменения при доо
системы, заштриховано.)
Запрос на
логическую запись
СУБД
описанию отображения данных ОБД °прД^ес^Т чтения файлов
ческие файлы и порядок доступа к н_ пр11ведена к нужному
содержащаяся в них информация подробно говорится
прикладной программе виду. Об этом более п-
в разд. 7.1.2 и 7.1.3. ,ая с помощью только что
Независимость данных, пол\ можно менять струКТ-1
описанного подхода, означаег’ ...чадНые программы. Рас •_
.файлов, не трогая при :пом "Р»лади^ Д
РИМ, например, рис. 7.36. 1 У в базу данных вкю
новая консультационная си ’ нй модифиииро^ собой
вый файл, а один уже СУШ изменения повлек
суиие он заштрихован).
корректировку описания отображения данных, однако сами при-
кладные программы остались без изменений. Как и раньше, по
логическому запросу будет выполнен ряд операций над файла-
ми базы данных. Однако прикладные программы об этом не
узнают, потому что они имеют дело только с логическими эле-
ментами информации, а не с тем, как информация хранится в
файлах.
Независимость данных, обеспечиваемая системой управления
базами данных, важна и по другим причинам. При желании в
любой момент могут быть заменены технические средства, на
которых реализована база данных. Например, вся она или’ же
ее часть может быть перенесена на запоминающее устройство
другого типа. Файлы могут быть реорганизованы, пересортиро-
ваны в различные последовательности или проиндексированы
другим набором ключей. Обычно это делает администратор
базы данных, который старается так организовать и хранить
данные, чтобы база данных использовалась с большей эффек-
тивностью. Все этим изменения можно сделать, нс оказывая вли-
яния па прикладные программы. На самом деле программы
вообще не в состоянии определить, были ли внесены такие из-
менения.
Из-за того что каждое обращение к базе данных осуществля-
ется при помощи описания отображения данных, использование
СУБД приводит к большим накладным расходам системы, чем
при выполнении программ, зависящих от данных. Однако вы-
года, получаемая от независимости данных и сокращения их
избыточности, обычно значительнее дополнительных накладных
расходов. Это особенно справедливо в случаях, когда содержи-
мое и структура базы данных являются предметом периодиче-
ских изменений при добавлении новых приложений.
7.1.2. Уровни описания данных
Как видно из предыдущего раздела, использование системы
управления базами данных делает прикладные программы не-
зависимыми от физического способа их хранения. Если в обыч-
ных файловых системах программист имеет дело с описаниям !
способов организации, создания последовательностей и индекси-
рования файлов, то при работе с СУБД программисту вес 1
детали обычно не известны. Но, даже если он с ними и зпз;
ком, он не смог бы этим воспользоваться, поскольку физичесм *
носитель базы данных может быть заменен в любое ври
Таким образом, прикладной программист должен иметь прс<
ставление о данных на логическом уровне, не связанном никик
со структурой файлов и другими вопросами физического xiK1
нения,
7.1. Системы управления базами данных
405
Информация, хранимая CVRn «
зователя может быть представлена по-рХомуСТ1а°[боГА ?°ЛЬ"
представлением является полное логическое бписз ин г Щ’’м
пых, называмое схемой. На рис 7 4 пока Л . 6 ла"'
схемы. Опа состоит из набора логических записей’ТЛ ТЭК°Й
пых, таких как СТУДЕНТ и КУРС. Некоторые из них соеТи‘
пены линиями, отражающими возможные отношения mSv
записями данных типов. Например, отношением <заХпе\щ,Х
задается, какой студент на какой курс зачислен. Предполагает,
ся, что это пример базы данных для гипотетического унипрпги
катггорий-диплома
| СПЕЦИАЛИЗАЦИЯ СРОК-ОБУЧЕНИЙ ♦
КУРС
ФАКУЛЬТЕТ НОМЕР
ОТДЕЛЕНИЕ
СТУДЬНТ
Запрос
слецйализируется*в
зачислен-на
нзучный-руководитель
студент-по-найму
ПРОФ- ПРЕП.^гСОСТАВ
преподаватель
ИН ФАМИЛИЯ АДРЕС
Iполучзсг-
I субсидию
ФИНАНСОВАЯ-ПОМОЩЬ
I вид РАЗмер
ФАМИЛИЯ ФАКУЛЬТЕТ 1мЕСТ0-РАБ(ПЬН
—X----------------------1----1
преподаватель-
по-найму
ПЛДТЕЖНАЯ-ВЕДОМОСТЬ
ИН ДОЛЖНОСТЬ
ОКЛАД
НАЛОГИ |
Рис. 7.4. Схема для простои базы данных университета.
тета. Элементы данных в логических записях дают представле-
ние о типе содержащейся в них информации. В реальной оазс
данных, возможно, будет больше типов логических записей, а
в каждой из них намного больше элементов данных.
Системы управления базами данных сильно различаются в
зависимости от типа записей и отношений, которые
держаться в схеме. Например, в некоторых системах. 4 <J ’
чтобы логическое представление базы данных 11 1 „
ческую или древовидную структуру, в то вРем^‘ ‘ .. между
допускается наличие более общих типов записями
записями. В некоторых системах явные связи ‘ 'чажаются ие.
вообще запрещены. В этом случае 0TH0^e ТОв данных. Об-
явно через значения соответствующих э* памкн нашей
суждение подобных моделей данных вых: ' можно найти в
книги. Дальнейшую же информацию и ссылки можно
Дейт [1981]. „пгпирекой структуры и содер-
Схема дает полное описание логи прикладных про-
чимого базы данных. Однако толику этой инфор-
граммистов используют лишь не .J имеет дело только с
мации; конкретная программа о > й. Описание данных,
несколькими типами записей и
"|>огРаммг- подсхема Обычно
у одной схемы существует много различных потсхем Кажтая
«У*лам
может быть использована поотлм»»» . подсхема а
ку списка студентов по их специализациирм'1руЮ111ен распечат-
зующей подсхему а, база данных I i K(>T / ,рограмме, исполь-
торого числа записей КАТЕ^ЖЖ^
ПРОФ-ПРЕП. СОСТАВ
преподаватель
ДИСЦИПЛИНА ___________________
ФАКУЛЬТЕТ. НОМЕР | ОТДЕЛЕНИЕ
^список-хтудентоэ
У ОТДЕЛЕНИЕ
КАТЕГОРИЯ-ДИПЛОМА
СТУДЕНТ-КУРСА____________
|ин | ФАМИЛИЯ^СПЕЦИАЛИЗАЦИя|
ОПЛАТА
ИН ФАМИЛИЯ АДРЕС с/п ВИД-РАБОГЫ ОКЛАД НАЛОГИ
3
Рис. 7.5. Три возможные подсхемы, соответствующие схеме на рис. 7 4.
ХЫстментааланнаЛ°Р0М 3а”ИСеЙ СТУДЕНТ («Дной для ка!
использована ПмТ спе.цнал"за“ии)- Подсхема б может о.
преподавателя ГТп! ^1'10"’ печатаюЩей списки групп каждого
ет трехуровневую^ т, тавлепие базы Данных в этом случае име-
преподаватетк? гк« Р^КТУРУ- ^ажДая запись, соответствующая
курсам „а котовых ™ < "аб°Р°,м 3аПИСей’ соответствующих
соответствующая xvnrv ,Л" Она пРеп°Дает; каждая завис,.,
записей списка етуп?иУ’ В СВОЮ очеРеДь связана с набором
бУДет использовятк/ Т0В’ ЧИСЛЯ1ЦИХСЯ на курсах. Подсхема в
ведомости всего уш пРогРаммой> обрабатывающей платежные
этой подсхеме еочрУп ерСИТГа- Каждая логическая запись в
служащему за р пл а ть?ИГ инфоРмацию’ необходимую для выдачи
ния о базе данныг^ГТопл^ совеРшенно различные представлю
мой, Т. е. должна rvrn?CXtMa д0лжна быть согласована со схю
манию, имеющуюся вСп™°ВаТЬ возможность извлекать инфор-
а является просто ее пппДСХеМе’ И И3 самой схемы. Подсхема
дмножеством; имена записей, элементы
данных и отношения те же что "-------------21
схемы. Однако это не обязя-ЛпС? " в соответствуют^-.
В подсхеме б прикладные всех 'в°Дсхем ЗСТН
записей, отличные от тех чтл раммы используют „
также использование иных имЛ иР*ЭТся и схеме ' Возмп^На
данных. Запись ПРОФ.-ПРЕП -СОСТАВ ЛРУГИХ ЭЛеМс”тар*ых
жнт только часть, а не всю ’ ишЬопмР ° ПОдсх^е б
записи ПРОФ.-ПРЕП.-СОСТАВ в схеме Чя’ СОответствУЮ11уРю
НА в подсхеме содержит всю шХ>п Запись ДИСЦИПЛИ
схеме. Запись СТУДЕНТ-КУРСА в падсТем^ ЗЭПИСИ КУРС в
мацию из записи СТУДЕНТ в схрма п вклю,|ает инфор-
ДЕНТ-КУРСА входит также и "шфор В ЗЭПИСЬ СТУ‘
студента, которая содержится в записи КАТЕГОРИЯ ЛИППп
МА, логически связанной с записью СТУЛЕнт Я'ДИПЛ0'
«специализируется-в». ^УДЕНТ отношением
Подсхема в состоит из единственной nnrtm^A*
ОПЛАТА, данные в которой могут бытЛфо
мощи трех различных записей схемы. Информация, касающая.
„лаКRP плмлгтк °' М0ЖеТ бь1ть взята 113 зап"с" ПЛАТЕЖ-
НАЯ-ВЕДОМОСТЬ, принадлежащей схеме. Такая информация
как фамилия служащего и его адрес, извлекается с использова-
нием отношений «студент-по-найму» и «преподаватель-по-наГь
му» из записей либо СТУДЕНТ, либо ПРОФ.-ПРЕП.-СОСТАВ,
какая больше для этого подходит. Поле данных в ОПЛАТА,
обозначенное С/П, показывает, к кому запись имеет отноше-
ние: к студенту, работающему по найму, или к преподавателю.
Подсхема дает прикладной программе наиболее отвечающее
ее нуждам представление о базе данных. За переводом инфор-
мации, содержащейся в базе данных, в форму, заданную под-
схемой, следит СУБД (разд. 7.1.3). В результате писать при-
кладную программу проще и легче, потому что программииу
не нужно использовать элементы данных и oi ношения, нс >
носящиеся к самой прикладной программе. чр0^ т ’ а не
схема помогает в обеспечении защиты дааиь1Х' 1 ,х‘не 01Ш-
имеет возможности обращаться к элемеш а д<
санным в ее подсхеме. „„„MV ^ппвня описания дан-
Итак, мы рассмотрели три разд и - И подсхемы> схему и
ных в системе управления база^н А оздацИя базы данных на
описание отображения данных. Д- а на3ываемые языки
каждом уровне СУБД пРименряппль3уемые прикладными про-
описания данных. Подсхемы, бном для Них языке onilt'a^11
граммистами, реализованы на у, ' в результате Расш“р м.
подсхем. Часто эти языки поя ..спользуемом языке пр 1 ‘
возможностей описания Дан,^1Х с03даются и поддерж дол-
мирования. Подсхемы однако, Qnp п°Д^ может
администратором базы А ставление данных в п Д •
ж си быть уверен, что пр Д ___ _______
быть получено из схемы и содержит только те элементы дан-
ных, которые разрешено использовать данной прикладной про-
грамме.
Сама схема и описание отображения физических данных
обычно используются только администратором базы данных.
Во многих системах язык описания схем тесно связан с языком
описания подсхем. Поскольку схема непосредственно приклад-
ными программами не используется, возможно также исполь-
зование и более общего языка. На язык описания физических
данных влияют типы логических структур, поддерживаемых схе-
мой, а также типы файлов и запоминающих устройств поддер-
живаемых СУБД.
Дальнейшее обсуждение и примеры языков описания дан-
ных можно найти в Дейт [1981].
7.1.3. Использование СУБД
В двух предыдущих разделах мы ввели основные понятия и
терминологию по системам управления базами данных. В этом
разделе мы завершим описание СУБД, для чего рассмотрим их
взаимодействие с пользователями и связь СУБД с другими
компонентами системного программного обеспечения.
Два основных способа взаимодействия пользователя с СУБД
показаны на рис. 7.6. Пользователь может паписать исходную
программу обычным способом, используя общецслевыс языки
программирования, такие как Кобол, ПЛ/1 или ассемблер. О
нако вместо имеющихся в этих языках операторов ввода-вьп -
да программист пишет команды на языке манипулирован.ri
данными (ЯМД), который предназначен для взаимодействия
пользователя с СУБД. Эти команды часто создаются так, что-
бы ЯМД казался простым расширением языка программирог.а-
ния. Как показано на рис. 7.6а, для перевода команд ЯМД
операторы языка программирования, которые вызывают п
граммы СУБД, может быть использован препроцессор. Пои
этого модифицированная исходная программа компилируем я
стандартным способом. Другой подход заключается в том, ч
бы изменить компилятор так, чтобы он сам обрабатывал <
рации ЯМД. Некоторые языки управления данными опреде.м
ются как набор операторов CALL, используемых в языке щ
граммированияД в результате чего отпадает надобность в
препроцессировании или модификации компилятора.
Другой подход к взаимодействию с СУБД, показанный '
рис. 7.66, не требует от пользователя написания програех
для осуществления доступа к базам данных. Вместо этого \
зователи вводят команды на специальном, задаваемом С< 1
языке запросов. Эти команды обрабатываются интсрпрсган'Г'
т. I. Системы управления базами данных
409
от гы гораздо быстрее
отлаживать nnnmo...
программы’
языка запросов, который для выполнения требуемых операций
вызывает программы СУБД. 1 ции
Оба подхода имеют свои преимущества. Использование язы-
ка запросов позволяет получить результаты -------
поскольку нет необходимости писать и
Языки запросов могут с успехом
применяться непрофессиональ-
ними программистами и том.,
кто программирует лишь от Х
чзя к случаю. Однако больше
сгоо языков запросов содержа
встроенные ограничения. II. ,
мер, бывает сложно или вообще
невозможно выполнить функцию
на которую язык не рассчитан'
^ другой стороны, ЯМД позво-
ляет
программисту
вать гибкость и все
использо-
возмож-
языков программирова-
ния общего назначения; однако
ности
этот подход потребует от поль-
зователей гораздо больших уси-
лий. В большинстве современ-
ных систем управления базами
данных имеется как язык за-
просов, так и ЯМД; при необхо-
димости пользователь выбирает
удобную для него форму взаимо-
действия. Дальнейшую информа-
цию о ЯМД, языках запросов
и их примеры можно найти в
Дейт [1981].
При обработке запроса СУБД
выполняет одну и ту же no-
Исходная
программа
С командами
на Я МД
Исходная
программа
С операторами
вызова
Объектная
программа
6.
Рис. 7.6. Взаимодействие с СУБД
посредством языка манипулиро-
вания данными (а) и языка за-
просов (б).
Интерпретатор
языка
•запросов
Пользо-
ватсль
I
следовательность операции вне з • йствия показаны на
ется язык запросов или Я' *Д- событий приходится на
рис. 7.7, Начало последовательности программы
момент, когда посредством запР Rn /шаг j на рисунке). Бели
А осуществляется обращение к гоамма А является иитер-
используется язык запросов, т р лагаетСя, что запросом
претатором языка запросов. 'данных. Поспелова-
лается требование чтения даш „нд базы данных а
тельность событий для других Р
Запрос от программы А формируется в теР‘^"”ах щая ПОд.
СМой ею подсхемы. Например, программа, исп задан-
схему, приведенную на рис. 7.5в, может зад с
кого служащего запись ОПЛАТА. Чтобы обработать этот за>
прос, СУБД сначала должна исследовать используемое опреде-
ление подсхемы (шаг 2). Она также должна рассмотреть от-
ношения между подсхемой и схемой (шаг 3), чтобы интерпре-
тировать запрос в терминах всей логической структуры базы
данных. Так, например, СУБД обнаружит, что для того, чтобы
снабдить программу А ожидаемой ею записью ОПЛАТА, ей
Рис. 7.7. Типичная последовательность выполняемых СУБД действий, (з
имствовано из Martin J. Computer Data — Base Organization, 2nd '
c. 1977, p. 83. Reprinted by permission of Prentice-Hall Inc., Engirt'
Cliffs, N. J.)
потребуется прочитать запись ПЛАТЕЖНАЯ-ВЕДОМОСТЬ cv -
мы для данного служащего (см. рис. 7.4). Вдобавок СУБ
потребуется для записи ПЛАТЕЖНАЯ-ВЕДОМОСТЬ, о кото-
рой идет речь, изучить отношения «студент-по-найму» и «прс-
подаватель-по-найму» и прочитать соответствующие завис'
СТУДЕНТ и ПРОФ.-ПРЕП.-СОСТАВ
После определения логических записей базы данных, ког ••
рые должны быть прочитаны (в терминах схемы), СУБД !!Т'
чает описание отображения данных (шаг 4). Эта операнд'
дает информацию, необходимую для нахождения пужн!
записей в файлах базы данных. В этот момент СУБД уже 1
ревела логический запрос записи подсхемы в физический 1
.чтение данных из одного или нескольких файлов. Эти запрет1
411
для файла ввода-вывода передаются о -----------------'
(шаг 5) с использованием запросов на °ПеРац»онной системе
ренных в гл. 6. Затем операционная“сист7мУЖИВание- ₽»«»«*
ввода-вывода Р(шаг“б)Л'в результате'"осуще®’0*™™ «S
„^требуемых записей из б^ы АаШ°УхТ?у^
После того как завершено пиппт
все данные, запрошенные приклаХ^'ш^г3114^14 операций
в центральной памяти. Однако эта пйюп раммой> находятся
быть преобразована в нужную прогоаммо ?14 еЩе должна
СУБД делает это посредством сравнения t±pMy’ И снова
В рассматриваемом нами примере СУБП Ы С подсхе-моп.
записи ПЛАТЕЖНАЯ-ВЕДОМОСТЬ в ™ извлечет Данные из
сей СТУДЕНТ и ПРОФМ 1РЕгГ.сп?тлТВеТСТВующих запи-
ОПЛАТА, запрашиваемую программой А. Запись ОПЛАТА"СЬ
Гр^ем;йП;°Мн:Тоам Обработка
завершается’. Наконец,
программе, предоставив ей все многообразие нийюриаШии о со”
стоянии, включая указания о возможных ошибках.
Подробнее о затронутых в разделе вопросах можно прочи-
тать в Уидерхолд [1983] и Дейт [1981]. Р 1
7.2. Текстовые редакторы0
практХееРсакиТИлюб5 текстовый Редактор стал важной частью
Не считаются вычислительной системы. Редакторы более
гарей вносящие' УД,1ЯМИ тРУда ТОЛЬКО программистов или секре-
вапианто,? Я„щих из«е".еиия в соответствии с новым авторским
М текста- Сейчас текстовый редактор получает все
нам признание в качестве основного средства общения с
mL «работников умственного труда» любого типа в тс пери-
м /’ когда они создают, организуют, изучают и обрабатывают
информацию, заложенную в ЭВМ.
В этом разделе мы рассмотрим интерактивные системы тек-
ового редактирования с точки зрения как пользователя, так
системы. В разд. 7.2.1 дается общее описание процесса рс-
Дактирования. В разд. 7.2.2 в дополнение к этому рассматрива-
ется различные типы устройств ввода-вывода и средств обще-
....Использованы работы Norman Meyrowilz and Andreis van Dam,
,n ^active Editing Systems: Part I and Part II», ACM Computer Surveys, ip
' H'bcr, 1982. Copyright 1982, ACM, Inc. В этих работах также содеР*икя
>'ihюлыю более подробный материал о процессе Редак1НР‘’1'| ’ лилщп.
’'II||JI- число (уц|(.Г|вуюших редакторов и приведена о н 1
pet),
пия с пользователем. В разд. 7.2.3 описывается структура тц.
личного текстового редактора и рассматривается ряд вопросов,
касающихся его системной организации.
7.2.1. Описание процесса редактирования
Интерактивный редактор — это программа, с помощью кото,
рой пользователь может создавать и изменять целевой доку-
мент. В понятие документа входят такие объекты, как про-»
граммы, тексты, формулы, таблицы, диаграммы, чертежи и фо-
тографии — все то, что может находиться на печатной страни-
це. Здесь мы ограничимся рассмотрением текстовых редакторов,
в которых первичными редактируемыми элементами являются
строки символов в целевом тексте.
Процесс редактирования документа — это диалог между
пользователем и ЭВМ, во время которого требуется решить че-
тыре задачи.
1. Выбрать часть целевого документа для отображения и об-
работки.
2. Определить, каким образом отформатировать и визуализи-
ровать полученный образ.
3. Задать и выполнить операции, изменяющие целевой доку-
мент.
4. Изменить в соответствии с этим образ.
Выбор части документа для отображения и редактирован!. ,
включает первый просмотр всего документа для нахожден!
нужной области. Поиск производится с помощью таких они
ций, как выдать следующую (предыдущую) страницу и пай'.и
по образцу. Во время просмотра определяется, где находит» (
нужная область; выбор объекта для отображения и работ;
осуществляется посредством операции фильтрации. С ее it-
мощью выделяется некоторое подмножество целевого доку и
та, например страница или оператор. Затем посредством Ф»
матирования создается визуальное представление (образ), т -
торое отобразит результат фильтрации на экране дисплея г...
па бумаге.
В реальном процессе собственно редактирования цел-.,
документ создается и изменяется при помощи ряда операи .
таких как вставить, уничтожить, заменить, передвинуть и
пировать. Функции редактирования часто ориентированы на у
боту с элементами, зависящими от типа редактора. Напрнм-
редактор, ориентированный на работу с рукописями, мо
оперировать такими элементами, как отдельные символы, с.'"
строки, предложения и абзацы; программно-ориентирован''-
редактор может работать с идентификаторами, ключевыми
вами и операциями.
7.2. Текстовые редакторы 413
___________-———— - — —— -— —--
В простейшем случае пользователь может ппп....
нумеит до конца. Последняя страница текста ГПЬ ДО'
вана, затем отформатирована, а полученный Жз ^ы^'
на внешнее устройство. После этого пользовате1и Г Леи
пример, уничтожить в образе первые три слона МОЖСт‘ на-
7.2.2. Интерфейс пользователя
Пользователю интерактивного редактора предоставляется
концептуальная модель системы редактирования,! е некоторая
абстрактная основа, на которой базируется и сам редактор и
все, с чем он работает. В сущности, простота понимания абст-
рактного представления целевого документа и его элементов
достигается в концептуальной модели при помощи набора прин-
ципов, которые описывают конечный результат операций редак-
тирования. В некоторых ранних строчных редакторах моделиро-
валась работа на клавишных перфораторах. В них существова-
ли операции над пронумерованными последовательностями
80-символьных строк-образов перфокарт. Операции выполня-
лись либо в пределах одной строки, либо над несколькими
строками. В некоторых более современных экранных редакто-
рах среда, в которой представлен документ, имеет вид квадра-
та, не ограниченного ни справа, ни снизу. Операции выполня-
ются над его частями без учета границ строк. Через «окно» на
дисплее пользователь видит только прямоугольное подмноже-
ство квадрата. Окно может передвигаться вправо и влево,
вверх и вниз, при этом визуализируются соответствующие на» in
Помимо концептуальной модели к интерфейсу пользования
относятся устройства ввода и вывода, а также < ,а<'’ ‘ '
язык системы. Освещению этих аспектов посвянг
яся часть раздела.
могоСтекстСЛУжат ДЛЯ ввода элементов редактируе-
мых элрмпи™ п ввеДениЯ" команд и для задания редактирус-
ром мпч- В’ $ТИ УстРоиства при использовании их редакто-
текстя ° Разделить на три категории: устройства для ввода
К vr ’ ?лавишнь,е устройства и координатные манипуляторы.
к ' ТР0иствам лля ввода текста или строк символов относится
_ внатура (как у пишущей машинки), на которой пользовате-
и нажатием и отпусканием клавиш вызывают генерирова-
. Фактически все имеющиеся в на-
стоящее время клавиатуре» системы QWERTY (первые
Шесть букв второго ряда клавиатуры). Предлагались и другие
обструкции клавиатур, некоторые из которых имели значитель-
ные преимущества по сравнению со стандартными. Однако воз-
что пи одна из них не найдет широкого применения в
иие соответствующих кодов
Стоящее время клавиатуры ЭВМ —
--~ ~ » л тх7 Г
ближайшем будущем, поскольку для этого потребуются значн.
тельные усилия по переучиванию.
Клавишные устройства или устройства выбора вызывают
прерывание или установку системного флага, что приводит к
выполнению прикладной программой определенных действий,
таким устройствам обычно относятся функциональные клави-
ши, имеющиеся на алфавитно-цифровой клавиатуре или на са-
мом дисплее. Клавиши могут моделироваться и программно—-
посредством визуализации строк текста или символов. Вместо
нажатия на клавишу пользователь выбирает строку или сим-
Координатные манипуляторы — это двумерные аналого-циф-
ровые преобразователи, отслеживающие действия, выполняемые
пользователем, и устанавливающие в зависимости от этого кур-
сор на экране. К таким устройствам относятся координатная
ручка управления курсором, экранные сенсорные панели, план-
шетки и «мышка». Последние два устройства чаще всего
используются для редактирования. Планшетка — это плоская
прямоугольная панелька, обладающая электромагнитной чувст-
вительностью. По ее поверхности перемещается либо игла, похо-
жая па шариковую авторучку, либо шайба — маленькое устрой-
ство, умещающееся в ладони. Планшетка передает системной
программе текущие координаты иглы или шайбы. Программа
может затем перевести эти координаты в экранные и поместить
курсор в соответствующее место. «Мышка» также умещается в
руке и похожа на шайбу. Ее движение по гладкой поверхности
вызывает относительное изменение местоположения, которое
сравнивается системной программой с некоторым образцом. Ко-
ординаты «мышки» опять-таки преобразуются в экранные, чю
Приводит к перемещению курсора.
Координатный манипулятор, совмещенный с клавиши!
устройством, позволяет задавать либо определенную точю
экране, начиная с которой должен быть введен или уничю/.у
текст, либо начальную и конечную точки строки символов,
торая будет обрабатываться. Фактически «мышка» или ш
имеет встроенные клавиши, позволяющие пользователю спин,
лизировать о выборе. Когда курсор указывает на нужный
мент, пользователь сообщает об этом нажатием клавиши
стема сопоставляет местоположение курсора с элементом
полняет требуемые действия. 11С.
Для моделирования координатного манипулятора ч<.
пользуют устройства для ввода текста со «стрелочными» ум
сорными) клавишами. На каждой из них изображена с | •
направленная вверх, вниз, влево, вправо. Нажатие на эг
виши вызывает генерирование соответствующей послсдо •
ности кодов; программа опознает ее и передвигает к}Р1
направлении, указанном стрелкой.
415
Все еще находящиеся в стадии исследования устройства
ввода голосом, преобразующие произносимые слова в тексто-
вые эквиваленты, могут стать в будущем устройствами для
ввода текста. Пока еще ограниченные малым словарем (содер-
жащим менее 1000 слов) анализаторы голоса, вероятно, скоро
приобретут коммерческую жизнеспособность.
Устройства вывода, используемые при редактировании и пер-
воначально ограниченные в области применения, становятся все
более разнообразными. Они нужны для того, чтобы пользова-
тель видел то, что он редактирует, а также результаты выпол-
нения операций редактирования. Первыми устройствами вывода
были (ныне устаревшие) телетайпы и другие литерно-нечатаю-
щие терминалы, использовавшие для вывода бумагу. Следую-
щие, «стеклянные телетайпы» создавались на основе электрон-
но-лучевых трубок (ЭЛТ). Они имели ЭЛТ в качестве экрана
и в сущности, моделировали работу обыкновенного телетайпа
(хотя некоторые операции, например возврат назад, были реа-
лизованы более изящно). В современных усовершенствованных
ЭЛТ-терминалах существует аппаратная поддержка для таких
О ___ __ — —
операции, как перемещение курсора, вставка и уничтожение
символов и строк, выдача строк и страниц. Новые автоматизиро-
ванные рабочие места, основанные на персональных ЭВМ с
дисплеями, обладающими высокой разрешающей способностью,
имеют многочисленные пропорциональные символьные шрифты
для выдачи реальных факсимиле твердых копий документов.
Таким образом, пользователь может получить представление о
том, как документ будет выглядеть на бумаге.
Существует несколько типов диалоговых языков текстового
редактирования. Самыми старыми способами общения редакто-
ра с пользователем являются набивка или ввод текстовых
команд. Пользователь набивает в виде текстовых строк как
сами команды, так и операнды. Все это пересылается редакто
ру, а затем обычным образом отображается на устройстве
При набивке спецификаций пользователь
ный вид всех команд или по крайней мерс и. ПОСТОянно
Если командный язык сложен, пользователь . . ' а10ЩНХСЯ
обращаться за описанием наиболее нвать помощь у
команд к руководству по системе £ вреМени, особенно
машины. Вдобавок набивка от ним эТИХ недостатков
У неопытного пользователя. На ус (function-key) кла-
направлено использование ^WK^TBCTCTByeT клавиша на кла-
виш При этом каждой команде соответству character)
виатуре. Например, команде «вставнтьсимв 1С^задаНис комащ
может соответствовать клавиш. клавишей, обычно сов:, с
Ды, определяемой функциональной клав.
с перемещениями курсора, что значительно ограничивает на-
бивку.
Для ввода часто встречающихся команд редактора обычно
требуется просто нажатие одной клавиши. Задание редко ис-
пользуемых команд и дополнительных возможностей может
быть осуществлено при помощи нажатия нескольких клавиш.
Чаще, однако, для изменения стандартного значения функцио-
нальных клавиш используются дополнительные клавиши особо-
го вида (такие как SHU T на печатающей машинке, переклю-
чающая регистры). Или же можно заставить алфавитно-цифро-
вую клавиатуру моделировать работу функциональных клавиш.
Например, пользователь, нажав управляющую клавишу одно-
временно с обычной, алфавитно-цифровой, вызовет генерирова-
ние нового символа, который будет воспринят как функцио-
нальный.
Для работы с системами, ориентированными на набивку
{typing-oriented systems), требуется хорошее знание системы и
языка, умение печатать на машинке. В системах, ориентирован
ных на функциональную клавиатуру, часто используется либо
совсем мало клавиш (при этом для формирования команд нуж-
но многократное их нажатие), либо слишком много уникальных
клавиш, в результате чего загромождается клавиатура. В лю-
бом случае при работе с такими системами от пользователе,
требуется еще большая ловкость, чем при использовании ста
дартной клавиатуры. На решение этой проблемы направлен
использование интерфейса, ориентированного на меню. Меню
это набор текстовых строк или образов, выраженных графши-
скими символами, изображающими объекты или оперши
Пользователь может задавать нужные действия, выбирая и в
меню. В меню, выдаваемом пользователю редактором, перин
лены только те действия, которые могут быть предприняты
текущем состоянии системы.
Сложности, касающиеся систем, ориентированных на меч
могут возникнуть, когда имеется много возможных деиствш
несколько путей выполнения каждого из них. Места для
на дисплее обычно отведено мало; поэтому, прежде чем
ся описание требуемой команды и ее дополнительных возм
ностей, пользователю будет последовательно выдано веско
меню в соответствии с иерархией. Поскольку квалифищи"
ному пользователю это может показаться скучным и ненхжи-
в некоторых системах допускается отключение управления у
{menu-control) и возврат к набивке и функциональным киш
шам. В других системах существует главное меню команд-
держащее чаще всего используемые функции, и второетеш-н=-
меню, где перечисляются прочие функции. Есть системы, в
торых меню выводится только тогда, когда пользова1сль
этом специально попросит. Например, для вывода меню с
ры
за-
яым перечнем возможна
•тиранием информаци*Н“х к°манд (ВОЧм
кнопку на «мышке» экРане) п0льз?ж,1°’ с временно
для выбора нужной' ^ама «мышка» “?ЬЗОватель мо Н11Ым
ДУ. а меню уничтс,- IKO^llДb, Затем Р°Жет быть Иажать
ретаюг все больш/к^Ц’,^
7.2.3. Структур по,. ,1РИ°6'
УРл редактора
Большинство текстов.
особенностей и маши “х Редакторов вне зависим,
структуру, аналогичиу.о «То кХа’ТаТ’
рис- 7-8- Блок,
Управление ,-......Даннше
Рис. 7.8. Типичная структура редактора. (Заимствовано из Meyrowits N,
van Dam A., «Interactive Editing Systems: Part I and Part 11», ACM Com-
puling Surveys, 1982, Copyright 1982, Association for Computing Machinery,
Inc.)
обработки команд воспринимает все, что вводится(чес1*<уюРСТрук-
лользователя, и анализирует признаки 11 сия' блока рЧень по-
ТУРУ команд. В этом смысле функции да’“ синтаксической
у*ожи на тс, • что выполняются в «'ХТсемантические
^d,ax компиляции. Как и при ком и, блоком обработки
£раммы могут вызываться неп0СРедсрр,.аптИческие программы
команд. В текстовом редакт0Реп" я Жирование и отображение.
Заложены такие функции, как ред
В Зек, ти
тДг^актирования и в промежуточном представлении Зт
вет нужные6 сем'авги^°ВаНО "“^"Р^ором1! который и вым’.
жуточного поелстяппЧеСКИе пРогРаммы- Использование проме-
е^а~=’ =
₽едХ=^^
вД,==
операций. Однако операции просмотра к о?ображештмогут
вызываться либо пользователем в явном виде, либо неявно о7.
рациями редактирования. Отношения между этими классами
операций могут быть гораздо более сложными, чем описано в
разд. 7.2.1. В частности, между тем, что содержится на экране
и тем, что может быть отредактировано, не обязательно долж-
но быть только одно отношение. Чтобы продемонстрировать это
рассмотрим подробнее на рис. 7.8 те блоки, которые имеют
принципиальное значение.
При редактировании документа начало редактируемой обла-
сти задается текущим указателем редактирования, которым и
управляет блок редактирования. Последний является объедине-
нием модулей, участвующих в редактировании. Указатель мо-
жет быть сброшен или установлен в явном виде пользователем
(например, посредством таких команд просмотра, как выдан,
следующий абзац или выдать следующую страницу), а также
неявно системой как побочный эффект от предыдущих опера-
ций редактирования (например, уничтожить абзац). Блок при-
смотра в редакторе выполняет реальную установку текущие
значений указателей редактирования и отображения. Гем са-
мым определяется точка, с которой при отображении или ।
дактировании начинается фильтрация.
При вводе пользователем команды редактирования соответ-
ствующий блок запускает фильтр, посредством которого im
нове текущего значения указателя редактирования и па
ров редактирующего фильтра создается новый буфер
рования. В параметрах, задаваемых как пользователем, ‘'
системой, содержится информация о границах текста, уча
щего в операции. Фильтрация может заключаться прост .
следовательном выборе смежных символов, начиная ’вцй,
точки. Или же она может зависеть от более сложных
задаваемых пользователем и имеющих отношение к сод 1 и,(.
му и структуре документа. В этом случае собираютс г ^оГо
ные части документа, в том числе и несмежные. \едакгИ'
семантические программы оперируют уже с буфере >( 1 'дМцо-
рования, являющимся, по существу, отфильтрованнь >
жеством структуры
сание носит умо3рнт~™ ДокУМеитаТТ'"------___4гГ
трация и Редактировав й хаРактег> 1ети«. Что7Г^^
ном виде не создан. ”е МогУт быть ра?д?СТвитс-,’ьноСт“Г<ь?Пи-
Аналогично ппи РазДеле11ы> а J*™ Фияъ-
мой области задается _бра>кении докумп,, ’ ер в Яв.
ния. Он поддер>КНВается блоЫЛ< Зна‘‘^м, ц’’ачало ^ображас
ЯЩИМ из модулей, и рели Л м ОГобР«хе/Л Теля °тобрХ-'
щего образа. Указатель мож^’б ЫХ Аля Ф^Йа*н?а' cotT<”
самим пользователем посрХЛ^
г——"Росмотра, либо
Текущим указатель
редактирования
Текущий указатель
отображения
Документ
Окно
Дисплей
Рис. 7.9. Простая взаимосвязь
жейня.
{Буфер редэк-/
j’Ироеэния
Буфер ото-
Пражски
между буферами редактирования и отобра-
неявно системой как результат предыдущей операции редактг
рования. Когда содержимое экрана требуется обновить, блок
отображения запускает соответствующий фильтр с
которого на основе текущего значс“”я^отХ^жсния. 11арамет-
параметров фильтра создается буфера 11 ак и системой,
ры могут быть заданы как п°л^ов;че^тве’СИМВОЛов, необхо-
В них содержится информация ок нх выбирать из
димых для заполнения экрана, i • > отобраЖения может
документа. В строчных редакт р^ых редакторах — ПРЯ*’ '
содержать текущую строку, а I ння поступает в PtL
угольный кусок текста Буфер которого
ряжение блока вИЗУал113а^.,,Стольный участок экр
буфера переносится на прямоуг^ ^зависн>
емый окном или полем ин отображения, остаВ1ейшем случае
Буфера редактирования и^раРному в простеи^^
мыми, могут быть свя > ’ 1 редактирует могут бы
они совпадают: польэовате-иь р оба б)Ф Р
ране (рис. 7.9), С ДРУ^й
на ЭК
X" ровани., „олМова.
«ражена. захотетьизм"Х °"а 6уДСТ ого’
словосочетания «гадкий v-re.?™ ? и 5(1 Се ВХОЖд«иия
го он использует такую loX ?° <лебедь>- Для это-
> к>ю команду, как change (изменить):
[1, 50] с/гадкий утенок/лебедь/
Одним из последовательно осуществляем my ,,rt
действий будет неявный переход^ первой КТ,Де
выбранные из документа строки с 1 по 50 о'» ^а,,ла- Затем
буфер редактирования. Здесь и осуще™ “
мены без соответствующей модификации образа ВсТучае об
наружения образца текущие значения указателей редХирова’
ния и отображения будут соответствовать последней из строк
в которой он был найден, а сама строка по умолчанию бу н а
занесена в буфера редактирования и отображения. Если образен
не найден, то в обоих буферах останется строка 75.
Буфера редактирования и отображения могут частично пе-
рекрываться или же один из них может полностью содержать-
ся в другом. Например, пользователь может затребовать поиск
конца документа, начиная с символа в центре экрана. В эт< и
случае фильтром редактирования создается буфер, куда поме-
щается текст документа, начиная от заданного символа и
конца документа. Буфер отображения содержит лишь ту ча - ,
документа, которая видна на экране. При этом только се конец
находится в буфере редактирования.
Окна обычно занимают либо весь экран, либо его ча<
Перенос содержимого буферов отображения в окна, запимы
щие часть экрана, особенно удобен для редакторов совр< 1
ных автоматизированных рабочих мест, оснащенных гршрг.
сними устройствами. Подобные системы обслуживаю!
окон, где одновременно отображаются различные часы
или нескольких файлов. Такой подход позволяет пользован,
выполнять операции внутрифайлового редактирования с г<>:
до большей эффективностью, чем в системах с едины. '
Перенос содержимого буфера отображения в omio
ствляется двумя блоками системы. Первый из них ' ' |: .
Сражения — формирует идеальный образ, обычно’ лс11; .
зависимое от устройства вывода промежуточное | Р у;ле.
Образ может быть очень простым и состоять в ci, '
щающегося в окне и организованного так, что « — t .
ках не обрывались посередине. Другая краиност
пия отформатированной и распечатанной стр R ODOg блок'
всеми формулами, таблицами и рисункам . получен11*1111
блок, визуализации — переносит идеальный о I ,
_ точная к°'
текста со
от блока отображения, на физическое устройство вывода паи.
более эффективным образом.
Внесение изменений на полноэкранном дисплее, подключен-
ном к через низкоскоростные линии связи (1200 бот и
меньше), производится медленно, если любая коррекция требу
.ст обновления всего экрана. В связи с этим большая исследи-
вательская работа ведется по созданию оптимальных алгорит-
мов экранного редактирования, основанных на сравнении теку-
щего содержимого экрана с последующим. В них используютс)
.такие внутренние возможности терминала, как внесение и уда-
ление символа. А передаются дисплею только те символы ко-
торые нужны для создания правильного изображения
Независимые от устройства операции ввода и вывода позво-
ляют упростить диалоговый язык. Отделение операции редакти-
рования и отображения от функций визуализации делает не-
нужным создание разных версий редактора для каждого ил
устройств. Во многих редакторах используются базы данных
управления терминалами. Вместо того чтобы держать последо-
вательности управления в программах визуализации в явном
виде, эти редакторы просто обращаются к терминально-незави-
симым библиотечным программам, таким как считать положе-
ние курсора (read cursor position) и сместить на строку вниз
(scroll down). Такие библиотечные программы при выборе под-
ходящей управляющей последовательности для конкретного ди-
сплея используют базу данных управления терминалами. Сле-
довательно, добавление нового терминала сводится к занесению
в базу данных соответствующего описания.
Блоки редактора работают с документом пользователя, на-
ходящимся как в основной памяти, так и в файловой системе
на диске. Загрузка всего документа в основную память может
оказаться невозможной; если же загружена только его часть,
а выполнение большого числа задаваемых пользователем опе-
раций влечет за собой чтение с диска, то редактирование мо-
жет осуществляться недопустимо медленно. В некоторых систе-
мах эта проблема разрешается посредством переноса всего
файла в виртуальную память с предоставлением операционно)!
системе возможности эффективного осуществления размещения
страниц по запросу. Или же реализуются входящие в редактор
программы страничного обмена, которые по необходимости чи-
тают в память одну или более логических частей документа.
Эти части нередко называют страницами, хотя между ними i
страницами виртуальной памяти, а также твердыми копиям)
Документа обычно ничего общего нет. Страницы осга|°тся
Новной памяти до тех пор, пока по требованию п
не будет загружена другая часть документа. ^пгямиапвян
Во внутреннем представлении системы доку/MeHJ структура
не как последовательность строк и символов, РУ
данных редактора, позволяющая осуществлять добавле-
ние, уничтожение и модификацию при помощи минимума опе-
раций ввода-вывода и перемещений символов. На диске доку-
мент хранится либо в виде такой же структуры данных, либо
в независимом от редактора общецелевом формате. В послед-
нем случае текст состоит из символьных строк, перемежающих-
ся управляющими символами, такими как конец строки (line-
feed) и табуляция (tab).
Редакторы функционируют в трех различных вычислитель-
ных средах, разделения времени, автономной и распределенной.
Каждая из них накладывает свои ограничения на структуру
редактора. В системе с разделением времени редактор должен
работать интенсивно, несмотря на загрузку процессора ЭВМ,
центральной памяти и устройств ввода-вывода. В автономной
системе редактор должен иметь доступ к тем же функциям,
что и в системе разделения времени. Этого можно частично
добиться использованием небольшой локальной операционной
системы. Или же функции могут быть встроены непосредствен-
но в редактор, если автономная система ориентирована на ре-
дактирование. В локальной распределенной сети с разделением
ресурсов редактор должен работать независимо на любой ма-
шине пользователя (как в автономной системе), а также уча-
ствовать в разделении ресурсов, например файлов (как в си-
стеме с разделением времени).
Некоторыми системами редактирования с разделением вре-
мени используются аппаратные средства самих терминалов. Та-
кого рода интеллектуальные терминалы содержат микропроцес-
соры и локальную буферную память, в которой может осуще-
ствляться редактирование. Небольшие редакции выполняются
не под управлением ЦП ведущего процессора, а самими терми-
налами. Например, редактор может передать текст объемом с
экран от ведущего процессора терминалу. Далее пользователь
волен добавлять или уничтожать символы и строки, используя
для этого буфер и управляющие команды терминала. После
того как буфер отредактирован, его обновленное содержимое
передается назад, ведущему процессору.
Преимущество такого подхода в том, что ЭВМ не касаются
никакие незначительные изменения или нажатия клавиш; 11
это и основной недостаток. Если используется неинтеллектуаль-
ный терминал, ЦП видит каждый набиваемый символ и можо
немедленно отреагировать на него, исправив ошибку, выл-’’
подсказку, изменив структуру данных и т. п. Что касается ।
теллектуального терминала, то недостаток постоянного контру
ля со стороны ЦП часто означает ограниченность в фу”к11^._
нальных возможностях, предоставляемых пользователю. В
цессе автономной работы на таком терминале пользован-',
может пропустить момент выхода системы из строя. С ДР)1
систем эх, где ввод каждого символа вызывает пре-
рывание ЦП, весь набор аппаратных средств редактирования
терминала может не использоваться в связи с тем, что ЦП не-
обходимо отслеживать каждое нажатие клавиши и обеспечить
эхо-контроль.
7.3, Системы интерактивной отладки”
Системы интерактивной отладки призваны помочь програм-
мистам в тестировании и отладке их программ. В настоящее
время существует ряд интерактивных отладчиков; однако ши-
рокое распространение получили лишь некоторые из них. Зна-
чение подобного программного изделия оценивается противо-
речиво. Неясно, в какой степени низкий процент использования
отладочных средств объясняется функциями и поведением са-
мих отладчиков, а в какой — незнанием их возможностей поль-
зователями. Тем не менее очевидно, что практически любой
пользователь испытывает нужду в удобных средствах интерак-
тивной отладки. В этом разделе рассматриваются некоторые
наиболее важные требования, предъявляемые пользователями к
отладчикам, а также ряд основных соображений по организа-
ции подобных системных услуг.
Ниже излагаются результаты, полученные во время совмест-
ной работы инициативной группы GUIDE/SHARE Language Fu-
tures Task Force (LFTF) и IBM. Группа LFTF была обра-
зована в результате деловых встреч двух основных групп
пользователей SHAPE и GUIDE в 1979 г. В ее задачи входило
предоставить фирме IBM информацию о взглядах пользовате-
лей на будущее прикладных средств. Одно из направлении ис-
следований было связано с интерактивной отладкой. В работе
Сейднер [1983] говорится о том, как фирма IBM расценивает
требования, предъявляемые к отладке, которые были сформи-
рованы группой LFTF. Все требования умышленно имеют об-
щий характер и не ограничиваются архитектурой Systeni/3/О,
каким-то одним программным продуктом или операционной си-
стемой.
В разд. 7.3.1 дается общее представление об основных функ-
циях и возможностях систем интерактивной отладки, рассмат-
риваются некоторые сопутствующие проблемы. В разд. . •
описывается связь отладочных средств с другими элементами
системы. Раздел 7.3.3 посвящен описанию интерфейса пользова-
лся в системах интерактивной отладки.
j, Использованы работы Rich Seidner and Nick дуС^NOTICES,
SOFTWARE ENGINEERING Noles ad SIGI 1
™gust j983 CopyrJg|lt 1983( Association for Computing •
7,3.1. Функции и возможности отладчиков
Ниже рассматриваются наиболее важные функции систем
интерактивной отладки. Реализация некоторых из них более
сложна по сравнению с остальными. В отдельных случаях не
совсем ясны пути наилучшей реализации.
Наиболее очевидными являются требования, предъявляемые
к задаваемым самим пользователем функциям тестирования
устройств (unit lest functions). Среди них значительная группа
связана со слежением за выполнением^ т. е. за наблюдением
И контролем за ходом выполнения программы. Например про-
граммист может установить точки останова, по достижении ко-
торых происходит останов программы. В результате появится
возможность проанализировать ее состояние и провести диаг-
ностику обнаруженных ошибок. Затем выполнение программы
может быть продолжено. Или же программист может задать
условные выражения, которые затем непрерывно вычисляются
в процессе выполнения. Как только какое-нибудь из них при-
обретает значение «истина», выполнение программы останавли-
вается. Аналогично может быть реализован останов программы
в результате выполнения заданной последовательности команд,
Если же функционирование программы может быть представ-
лено графически, имеет смысл попробовать прогнать ее с раз-
личными скоростями, называемыми аллюром (gaits).
В системах отладки должны быть реализованы и такие
функции, как трассировка и обратная трассировка. Трассировка
(tracing) позволяет следить за ходом выполнения логических
операций и за изменением данных. Она может осуществляться
на разных уровнях детализации: модульном, подпрограмм,
команд ветвлений и т. п. Трассировка может также основывать-
ся на вычислении условных выражений, о чем говорилось выше.
Обратная трассировка (traceback) может показать маршрут,
который привел к текущему оператору. С ее помощью можно
увидеть, какой оператор изменил значение данной переменной
или параметра. Такая информация должна быть представлена
в символической форме. Например, скорее следует выдавать
номера операторов, а не их шестнадцатеричное смещение 1).
В отладочной системе важно иметь также хорошие средства
отображения программ. Должна существовать и возможность
вывода отлаживаемой программы вместе с номерами операто-
ров. Пользователю следует разрешить задавать уровень ото-
бражения. Например, программа может быть выведена в то?л
виде, как она написана, после макрорасширения и т. ji. По-
лезно также иметь средства модификации и пошаговой пере-
*’ Имеются в виду языки типа ассемблера и Бейсика, в которых oiK
раторы нумеруются. — Прим, ред.
компиляции в процессе отладки. При этом система должна
сохранять все заданные отладочные спецификации (точки оста-
нова, режимы отображения и т. д.), с тем чтобы программисту
не пришлось заново выполнять отладочные команды Нужно
чтобы существовала и возможность вывода любых переменных
и констант в символьном виде и их модификации с последую
щим продолжением выполнения программы. Тем самым вне
зависимости от средств, используемых в действительности до-
стигается эффект интерпретации. ’ А
В системах интерактивной отладки должны быть реализо
ваны и многие другие функции и возможности. Их описание
можно найти в Сейднер [1983].
При реализации в отладочной системе описанных выше
функций должен учитываться язык, на котором создана отла-
живаемая программа. Многие прикладные системы и средства
предоставляемые пользователю, допускают использование раз-
личных языков программирования, при работе с которыми хо-
телось бы иметь единый отладочный инструмент. Команды от-
ладчика, активизирующие действия и инициирующие сбор дан-
ных о выполнении программы, должны быть общими для всех
языков. Однако специфику языка тоже нужно принимать во
внимание, чтобы процедуры, арифметические и логические
операции могли кодироваться с учетом синтаксиса этого
языка.
Реализация этих требований оказывает влияние и на отлад-
чик, и на остальное программное обеспечение. При передаче
управления отладчику выполнение отлаживаемой программы
временно приостанавливается. После этого отладчик должен
суметь определить, на каком языке написана программа, и со-
ответствующим образом осуществить настройку. Более того,
он должен изменять настройку всякий раз, когда программа,
написанная на одном языке, вызывает программу, написанную
на другом языке. Чтобы избежать недоразумений, отладчику
следует информировать об этом пользователя.
Само использование настройки оказывает немалое и разно-
образное влияние на диалог с отладчиком. Например, операто-
ры присваивания, изменяющие значения переменных в процес-
се отладки, должны быть написаны в соответствии с синтакси-
сом и семантикой исходного языка программирования. Если в
Коболе пользователь должен ввести команду MOVE 3.5 1О а,
то в Фортране она будет иметь вид А = 3.5. Точно так же в \с
Ровных выражениях должна использоваться система о означе
ний исходного языка. Условие «А не равно в» BRnporf пп0.
на Коболе будет иметь вид IF А NO Г EQUAL ТО »
Тамме на Фортране: IF(A.NE.B). Аналогичные разли чия: су
Шествуют и для форм представления операторов, ьп
Won и т, п,
42
компиляции в процессе отладки. При ЭТОм
сохранять все заданные отладочные спецификами, /Ма ДОлжиа
нова, режимы отображения и т. д ) с тем ч-Мл <точки °ста-
не пришлось заново выполнять отладочные™ко^нлы₽айМИСТу
чтобы существовала н возможность вывода любы, п™?1уЖН°’
„ констант в символьном виде „ их „о^пХш с п’о Х’™
ШИМ продолжением выполнения программы. Тем caZ вне
зависимости от средств, используемых в действительности до-
стирается эффект интерпретации. ’ до
I В системах интерактивной отладки должны быть реализо-
ваны и многие другие функции и возможности. Их описание
можно наити в Сейднер 11983]. °
При реализации в отладочной системе описанных выше
функций должен учитываться язык, на котором создана отла-
живаемая программа. Многие прикладные системы и средства
предоставляемые пользователю, допускают использование раз-
личных языков программирования, при работе с которыми хо-
телось бы иметь единый отладочный инструмент. Команды от-
ладчика, активизирующие действия и инициирующие сбор дан-
ных о выполнении программы, должны быть общими для всех
языков. Однако специфику языка тоже нужно принимать во
внимание, чтобы процедуры, арифметические и логические
операции могли кодироваться с учетом синтаксиса этого
языка.
Реализация этих требований оказывает влияние и на отлад-
чик, и на остальное программное обеспечение. При передаче
управления отладчику выполнение отлаживаемой программы
временно приостанавливается. После этого отладчик должен
суметь определить, на каком языке написана программа, и со-
ответствующим образом осуществить настройку. Более того,
он должен изменять настройку всякий раз, когда программа,
написанная на одном языке, вызывает программу, написанную
на другом языке. Чтобы избежать недоразумений, отладчику
следует информировать об этом пользователя.
Само использование настройки оказывает немалое и рази
образное влияние на диалог с отладчиком. Например, orjepaj
ры присваивания, изменяющие значения переменных в 1
се отладки, должны быть написаны в соответи1ьии с &
сом и семантикой исходного языка nPorPaMM,A?r)Vp 3'5 то д,
Коболе пользователь должен ввести ксшанду так же в ус-
то в Фортране она будет иметь ~ ь я СИСТема обозначе-
ловных выражениях должна использов в программе
НИЙ исходного языка. Условие «А не Р^°^овв^Ра ‘ пр0-
на Коболе будет иметь вид IIFрА N д J чные различия су-
грамме на Фортране: IF(A.NE.B). Ан 0 ключевых
Шествуют и для форм представлен
слов и т. п.
Система обозначений, используемая при задании определен-
ных отладочных функций, соответствует языку отлаживаемой
программы. Однако сами функции, по существу, не зависят от
исходного языка программирования. Для выполнения операто-
ров отладчик должен иметь доступ к информации, собранной
языковым транслятором. Однако внутренние форматы словарей
символов у различных трансляторов сильно различаются; это
касается и информации по расположению операторов. Трансля-
торы и ассемблеры будущего должны быть настроены на еди-
ный интерфейс с системой отладки. Это можно осуществить за
счет создэния языковыми 7рзнсляторами ис зависящей от их
внутреннего представления и оформляемой в стандартной внеш-
ней форме информации для отладчика. Другой способ заклю-
чается в создании на этапе трансляции интерфейсных модулей
отладчика, которые осуществят преобразование запрашиваемой
информации к стандартному виду, не зависящему от языка, на
котором написана отлаживаемая программа.
Сходные вопросы возникают в процессе отладки при ото-
бражении исходного кода. Опять-таки существуют две основные
возможности. Языковым транслятором может быть создан ис-
ходный код пли листинг, оформленный в соответствии со стан-
дартом, чтобы отладчик мог единообразно им руководствовать-
ся. Или же транслятор может снабдить отладчик интерфейсным
модулем, который в ответ па запросы, поступающие от отлад-
чика, осуществляет управление и отображение.
Важно также, чтобы отладочная система умела работать с
оптимизированным кодом, обычно используемым в процессе
эксплуатации программ. Однако требования, предъявляемые к
обработке оптимизированных кодов, могут создать много про-
блем для отладчика. Тем не менее возврат к неоптимизнрова
ним видам кодов только потому, что определенные проблемы
исчезнут, не оправдан. Мы рассмотрим только некоторые
пикающие сложности. Дальнейшую же информацию мсъь. j
найти в Сейднер [1983].
При многих оптимизациях осуществляется реорганизуй -
сегментов кодов в программе. Например, из циклов Moiy^ '
удалены инвариантные выражения, отдельные циклы оби
йены в один или цикл может быть частично развернут в 1
цикловый код. Избыточные выражения могут быть ликвиди.
ваны; в некоторых случаях возможно вообще исчезнои
операторов. Блоки кодов могут быть реорганизованы в ил
.уничтожения лишних команд ветвления для обеспечения > •
эффективного выполнения программы. Примеры некоторь ч
этих преобразований можно увидеть в разд. 5.3.3. ?
Все эти виды оптимизаций создают сложности для •
чика. Пользователь системы отладки имеет дело с исходной
Граммом в том виде, который она имела до оптимизации.
нако реорганизация кодов и^о ---"---------
я<ет повлиять на трассипг>пг,ЗМеняет поРядок виш,п
даже на количеств,? оперРатооов₽рСполо*ание точное?!' " мо'
жет оказаться еложпыЛ™^,^'1 ““"зружеаТоХ?^, "
ине в исходной программе. ТЬ ее "'тинное м«то„ахож,?’
Различного рода проблемы воз,,,,,, Д
мон для переменных. Когда программГг " С памя™°. отвод,,,
переменно» в основной памяти А а тРаислнруется Дс?”-
location). Однако, и об эЛм’говор^Г? .С“°Я
переменных в целях увеличения скорости na/A 522’ 3,,аЧ€н»я
время от времени храниться в реги^оаГп У”а К Н1,м м°пт
шиеся к этим переменным, используют зпаiem,T«°₽“’ обраща|°-
а регистрах, а не в ячейках памяти. По, такой 'аходящ"'«
не возникает проблем с отображением значка 0птимиза»ин
вых. Однако если в процессе отладки пол™ о” а~зк ПСре“с"-
значение переменной в памяти то оно пп„ ? « изменит
волнения программы, вероятно, не будет исполмова'ю'лиато’
гично в случае глобальной оптимизации значение перемХй
может быть все время присвоено регистру. Тогда соответств ю
щая ей ячейка памяти может вообще не существовать '
Отладка оптимизированных кодов требует значительной по-
мощи оптимизирующего транслятора. В частности, он должен
сохранять информацию обо всех преобразованиях, сделанных в
программе. К подобной информации можно дать доступ как
программисту, так и отладчику, который, где это имеет смысл,
должен использовать ее для модификации запроса, сделанного
пользователем. Тем самым будет выполнена требуемая опера-
ция. Например, окажется возможным достижение эффекта оста-
нова программы по контрольной точке, установленной на уни-
чтоженном операторе. Аналогично модифицированное значение
переменной может быть сохранено как в регистре, так и в
ячейке памяти. Однако некоторые более сложные оптимизации
так просто не могут быть обработаны. В этих случаях отлад-
чику не следует пытаться имитировать работу функции, а п\
но проинформировать пользователя о том, что на этом \ровне
она не реализуема.
7.3.2. Взаимодействие с другими элементами системы
Существует множество Разд"4^ При
интерактивного отладчика с друг тпРбованием к отладчику
этом1 единственным самым важным требование^
является его доступность в moboi Опепационного окружения,
ет, что он должен казаться ^^ТЬйЮсистеРмы. Так как аварийную
неотъемлемой составляющей бывает сложно или ие
ситуацию, возникшую в пР0Гра .,.„а существовать возможнее .
можно повторить специально, должна сущ
Немедленного доступа к отладчику при обнаружении
ошибки. Таким образом, интерактивный отладчик должен
тесно взаимодействовать и с такими составляющими операци-
онной системы, как диалоговые подсистемы.
Например, у пользователей должна существовать возмож-
ность отладки программ в процессе их эксплуатации. Такого
рода отладка даже важнее, чем та, что производится во время
отработки системы. Это объясняется тем, что при выходе из
строя системы может остановиться зависящая от нее работа.
Кроме того, многие программные ошибки, возникающие в про-
цессе эксплуатации, вообще не могут быть повторены во время
тестирования.
Отладчик должен разрабатываться с учетом безопасности и
целостности элементов системы. Нельзя допустить использова-
ние отладчика кем бы то ни было в целях получения доступа
к данным или кодам, иными способами не доступным. Не дол-
жно существовать и возможности нарушать никоим образом
целостность системы. Для входа в отладчик должны применять-
ся традиционные методы авторизации, а каждое вхождение в
него фиксироваться. Одним из преимуществ отладчика, по
крайней мере по сравнению с дампом памяти, является возмож-
ность доступа к текущей информации. В дампе же содержится
лишь случайно оказавшаяся в памяти информация.
Деятельность отладчика должна быть согласована и с су-
ществующими компиляторами и интерпретаторами, и с темп,
что будут созданы в дальнейшем (об этом говорилось в преды-
дущем разделе). Предполагается и далее использовать средства
отладки на существующих языках. Требования, предъявляемы
к кросс-языковым отладчикам, дают возможность надеяться, чт ;
подобные средства будут применяться наряду с индивидуаль-
ными языковыми отладчиками,
7.3.3. Требования, предъявляемые
к интерфейсу пользователя
Пользователи критически относятся к поведению ингелл-
тивной системы и к тому, что она собой представляет. Возу
но, недовольство средствами отладки вызвано их нови
для пользователя. Поэтому лучше всего иметь дел
системой, которая имеет простую организацию и позволь
вести диалог на привычном языке. В отладочной системе до-'
ны быть реализованы функции, тесно связанные с зада и;
пользователей. Все это значительно облегчает знакомство с
стемой и ее использование. т
Если диалог осуществляется с помощью дисплеев,
использовать все заложенные в них возможности. Главное .
имущество таких устройств — в большом количестве отобра-'
У C"«»UHHTepa„„
429
емой на них информации и „
л быстро изменена. Такнов ТОм’ что она м
дакторы, сокращают обТем ?»АСтва’ Как меню ТТ С,41ь ЛетКо
в8Телем информации. Все Это°обМ°Й “ Эап°мин^мЛаННыс Рс'
„„терактивной отладки. облегчает иснолъзова ? Польз°-
Б С системой удобно работать СИстсм
выполнить пользователю заложеныТпЛадачи’ вторые ,,v
должны иметь названия, соотвеХуюшиаППЗац1^ Е*
циях следует предусмотреть все япЛ ЩИе за^чам. В ине?. ю
зователю. Названия должны помоч^ТТг'’ АОСТУп‘’ые пздъ-
Основным недостатком систем с меню Л 0|Ч‘ частей
них прямого маршрута, у пользователя то^СЯ ОТСУТС™Щ в
возможность непосредственного доступа к 5"а существовать
без прохода по всей иерархии. выбранному им меню
Хорошо, конечно, если в наличии
устройства и такие средства, как меню оТХо^и Н0ЭКРанные
сутствии отладочная система должна поддепжХЛ X ИХ от'
терактивных пользователей. Любое действие пользователя7 oev'
ществляемое на полноэкранном терминале, должно иметь эт-
Валент в линейном отладочном языке. Так, должен существовать
полный функциональный эквивалент между командами и меню.
у Командный язык должен иметь ясный, логичный и простой
синтаксис, а также как можно более походить на язык про-
граммирования. Команды должны быть преимущественно про-
•I, '
f
стыми, а не составными, и содержать как можно меньше пара-
метров. Во всех командах для обозначения параметров следует
использовать одинаковые имена. Автоматически должна прове-
ряться правильность таких характеристик параметров, как тип
и диапазон значений. Для большинства параметров должны
существовать значения, используемые по умолчанию.
Форматы команд должны быть как можно
В командном языке следует свести к м’111"?1'Д’; в Доступ к
скобок, кавычек и других специальных символов. Дост;
справочной информации нужно обеспе i
можно. « полжна быть реа-
В любой хорошей пНтеРа1т7р?'р 'существенную помощь нс-
лизована функция помощи lltL' Дю можно оказать, выдав
опытному или случайному ПОЛЬ ДмаНД. Для ОПЫТНЫХ ПО >
Обыкновенный перечень воз моа пы • специфичной и мйо^
зователей функция HELP,1ElP на экран может бы
Уровневой. Посредством HLL лЯ которых имеется д()
список дополнительных ФУрТ осуществляться пономЧ -курссра.
тельный текст. Выбор может осущ ипом°п1И
"мени дополнительно» ФУ доступна в лю»' больше в«-
фУнкция HELP должна °ыть fT„’ся ситуация, тем
Са отладки. Чем сложнее поТпебуется помо
Р°ятностЬ) что пользоватед!
Приложения
Приложение А
Система команд и способы адресации УУМ/ДС
Система команд
При описании системы команд для обозначения соответству-
ющих регистров используются прописные буквы. Буквой ш обо-
значены адреса в оперативной памяти, а буквой п — целые
числа в диапазоне от 1 до 16. Идентификаторы регистров име-
ют обозначения rl и г2. Скобки используются для обозначения
содержимого области оперативной памяти или регистра. Так,
выражение вида А <—(/лг .. т + 2) означает запись содержимого
оперативной памяти с адреса т по т 4- 2 в регистр А, а выра-
жение вида tn .. ш + 2<—(А) — запись содержимого регистра А
в слово, начинающееся с адреса т.
Буквы в столбце «примечания» имеют следующие значения:
Р — привилегированная команда;
X — команда, исполняемая только на модели ДС;
F — команда арифметики с плавающей точкой;
С — по значению результата операции (<,=,>) устанав-
ливается код условия.
В столбце «формат» указывается, какой командный формат
УУМ/ДС должен использоваться при ассемблировании коман-
ды; 3/4 означает, что может использоваться либо формат 3,
либо формат 4. Для стандартной модели УУМ все команды
ассемблируются в формате, описанном в разд. 1.3.1 (он совме-
стим с форматом 3). Неиспользуемые поля команды (например,
такие как адресное поле в команде RSUB) содержат пулевые
значения.
Форматы команд
Формат 1 (1 байт)
Формат 2 (2 байта)
8 4 4
op ri г2
Приложен не А. Система кли.... .
уУМ/ДС 441
Мнемокод ADD m Формат Код операции Результат
ADDF m ADDR г1,г2 AND m CLEAR rl 3/4 3/4 2 3/4 2 18 58 90 40 В4 А (А) + (и .* F- г2 - (г2) + (г!) А (А) & (о. г! ♦- о иримецанме • "• х F X ••
COMP m 3/4 28 (А) : (га..m+2) X
COMPF m 3/4 88 <F> 2 (m..m+5) с
COMPR rl,r2 2 АО (Г1) : (г2) X F с
DIV ш 3/4 24 А *“ (А) / (ш..п+2) х с
DIVF m 3/4 64 F (F) / (m. .т+5)
DIVR rl,r2 2 9С г2 - (г2) / (г!) Л F х
FIX • 1 С4 А ♦“ (F) [ прербравоввииё в целое) X Р
FLOAT 1 СО F <- ( А) [преобразование в вещественное] X F
HIO •Д F4 Прекратить обмен по каналу номер [А] Р X
J m 3/4 ЗС PC <- m
JEQ m 3/4 30 PC 4— m if СС set to »
JGT m 3/4 34 PC 4- m if CC set to >
JLT m 3/4 38 PC«-u if Ct set to <
JSUB m 3/4 48 L ♦- (PC); PC «- m
LDA m 3/4 00 A <— (m. ,m+2)
LDB m 3/4 68 В *- (m..n+2) X
LDCH m 3/4 50 A [ младший байт] <— (m)
LDF m 3/4 70 F *- (m. . m+5) X F
Lt)L m 3/4 08 L «— (m. .m+2)
LDS m 3/4 6С S (m. .m+2) X
LDT m 3/4 74 T (<n. .ш+2) А
LDX m 3/4 04 X (m.. m+2) Р Y
LPS m 3/4 DO Загрузить состояние процессора информацией, нанимающейся Г А
адресом (разд» 6.2.1)
MUL ш 3/4 20 А 4- (А) • (»••®+21 X F
MULF m 3/4 60 F <- (F) ♦ (0..Ш+5) X
MULR г1,г2 WORM OR m RD m 2 1 3/4 3/4 98 С8 44 D8 г2 ♦- (г2) • (HJ F «_ (F) [нормелим»#»**”] А (Л) 1 I®1 ,я+^ А • данных с устройств»» >• (®) X г р •
. КОД
Мнемокод Формат операции Результат
Примечание
RMO Г1,Г2 2 AC rZ (rl) X
RSUB SHIFTL Г1.п SHIFTR г!,п SI0 SSK И STA Л STB m STCH л STF m STI m STL m STS m STSW m STT m STX m SUB m SUBF m SUBR rl,r2 SVC n TD m TIO 3/4 2 2 1 3/4 3/4 3/4 3/4 3/4 3/4 3/4 3/4 3/4 3/4 3/4 3/4 3/4 2 2 3/4 1 4C A4 A3 FO EC ОС 78 54 80 D4 14 7C E8 84 10 IC 5C 94 BO EO F8 PC 4- (L) rl «- (rl); леьыи циклический X сдвиг на п разрядов. (В ассем- блированной команде г2’П-1} Г1 4- ( rl) ; Правый сдииг на п X разрядов с занесением в освобо- дившиеся разряды значений стар- ших разрядов (Н). {В ассембли- рованной команде г2=п-1) Активизация канала в/в номер (А); Р X адрес канальной программы задаётся в (S) Ключ защиты для адреса m Р X <- (А) (разд.6.2.4) П». .m+2 (А) ш. .т+2 4- (в) х тп 4- (А) [ младший байт] и. ,т+5 <- (F) X F Значение интервального таймера ь— Р X (го..ш+2) (разд. 6.2.1) Л)..пН2 4- (L) ш. .ш+2 4- (5) X m.,m+2<-(SW) Р ш •»tn+2 4- (т) X Ш. ,Ш^2 4— (X) А 4- (А) * (и..ш+2) F <— (F) ** (т,,ш15) X F г2 4- (г2) - (rl) X Генерирование 5VC прерывания. X {В ассемблированной команде Проверка устройства,заданного в (у1) р Проверка канала В/В с номером (А) Р X с с
TIX m TIXR rl ITO и 3/4 2 3/4 2C B8 DC X (X) + 1; (X) : X (X) + 1; (X) : (rl) Устройство,заданное в (т) <- (А) р X с с
[младший байт}
Формат 3 (3 байта)
6 111111 12
Формат 4 (4 байта) ~~~------—----
Способы адресации
Ниже даются описания способов адресации кптлп
зуются для форматов 3 и 4. Комбинавви 1?» Рые ИСПОЛ1"
не включенные в таблицу, рассматриваются КпюГ,
Сочные. В третьем столбце таблицы буква “псполыпЛ!,01”"'
обозначения константы в диапазоне от о до 4W5 К? ”
памяти, о котором известно, что о„ лежит в этом‘ZaS
Буквой т обозначен адрес или целое число больше чем 4095
Дополнительную информацию можно найти в разд 132
Символы в столбце «примечания» имеют следующий'смысл:
4 — командный формат 4;
D — команда с прямой адресацией;
А — ассемблер выбирает адресацию либо относительно счет-
чика команд, либо относительно базы;
S — совместима с командным форматом стандартной модели
УУМ. Значения операндов могут находиться и диапа-
зоне от 0 до 32 767 (подробнее см. в разд. 1.3.2).
Тип Разряды-признаки
адресации л I х b р е
операнд Приме'лимй
.Простая
q
о
о
о
1
Коешешя
I
О
О
1
о
о
о
1
о
о
о
1
о
о
X
о
а
о
I
о
Непосредственней
I
•1
о
о
о
о
D
о
о
о
1
1
1
1
О
о
о
о
о
о
о
I
о
о
о
а
0
0
0
1
о
о
1
о
о
о
1
б
о
0
□
а
I
о
о
о
1
о
о
Обозначение
в языке
ассемблера
Вычислений
целевого
адреса ТА
О
а-
□
ср О disp (TA)
4 Ор л addr (TA)
Ор а (PC) ♦ dU-Sj? (TA)
Ор m (В J + disp (TA)
ср с.х disp + (X) (TAJ
iop п.Х ftddr ♦ М I i A)
ОР ор ОР Ср й,Х Л4Х fit а.Х (PC) < di3p * IX) (В) * d!sp + IM fc/p/e/cUsp Ь/p/e/disP * (XJ (TA) (TA) (TA) (TA) ((TAI)
ор disp ((TAJ)
fOp ср ор Сл ®л Ctddt* (PC) * dbp (B) 1 diep ((TAJ) ((TAD ?A
op о disp . 5A
fop » л OddT (PC) * dis? n TA
Ор ор я (B) + dlsp
D
4 D
D
4 D
Ь
D
D
4 0
А
А
D
4 U
‘А
А
1
1
1
1
0
0
1
1
а
1 -
А
I
3
3
7'аблица символов кода ASCII
Код Символ Код Символ Код Символ Код Символ
00 NUL 20 SP 40 @ 60
01 SOH 21 1 41 А 61 а
02 STX 22 It 42 В 62 b
03 ETX 23 43 С 63 с
04 EOT 24 $ 44 D 64 а
05 ENQ 25 % 45 Е 65 е
06 ACK 26 к 46 F 66 f
07 BEL 27 > 47 G 67 g-
08 BS 28 ( 48 Н 68 h
09 Hf 29 ) 49 I 69 i
ОА LF 2A * 4А J 6А j
ОВ VT 'SB + 4В К 6В k
ОС FF 2C 9 4С L 6С 1
0D CR 2D 4D М 6D m
ОЕ SO | 2E • 4Е N 6Е n
OF SI 2F 4F 0 6F 0
10 DLE 30 0 50 р 70 P
11. DC1 31 1 51 Q 71 q
12 DC2 32 2 52 R 72 г
13 DC3 33 3 53 S 73 s
14 DC4 34 4 54 Т 74 t
15 NAK 35 5 55 и 75 u
16 SYN 36 6 56 V 76 V
17 ETB 37 7 57 W 77 w
1.8 CAN 38 8 58 * X 78 X
19 EM 39 9 ' 59 Y 79 У
1А SUB ЗА • а 5А Z 7А z
1В ESC ЗВ • 5В [ 7В {
ic FS ЗС < 5С 7С 1
ID GS 3D =Х 5D ] 7D }
IE RS ЗЕ > 5Е А 7Е
IF US 3F ? 5F 7F DEL
Примечание. Коды символов приведены в шестнадцатеричном