М. В. Ломоносова Факультет вычислительной математики и кибернетики В. Г. Баула Введение в архитектуру ЭВМ и системы программирования Москва 2003 Предисловие Данная книга

Вид материалаКнига

Содержание


11. Понятие о системе программирования.
11.1. Компоненты системы программирования.
Служебные программы системы программирования
Информационное обеспечение системы программирования
11.2. Характеристики исполняемых модулей.
11.2.1. Перемещаемые модули.
11.2.2. Повторно-выполняемые модули.
11.2.3. Повторно-входимые (реентерабельные) модули.
Подобный материал:
1   ...   25   26   27   28   29   30   31   32   ...   37

11. Понятие о системе программирования.


Как мы уже упоминали в начале нашего курса, все программы, которые выполняются на компьютере, можно разделить на два класса – прикладные и системные. Вообще говоря, компьютеры существуют для того, чтобы выполнять прикладные программы, однако понятно, что нас то в первую очередь будут интересовать именно системные программы.☺

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

В другой класс входят системные программы, предназначенные для автоматизации процесса разработки и реализации новых программ. Программы этого класса входят в системы программирования. Не надо, однако, думать, что система программирования состоит только из таких системных программ, которые помогают писать новые программы. Ниже перечислены все компоненты, входящие в систему программирования.

11.1. Компоненты системы программирования.

  • Языки системы программирования. Сюда относятся как языки программирования, предназна­ченные для записи алгоритмов (Паскаль, Фортран, С, Ассемблер и т.д.), так и другие языки, которые служат для управления самой системой программирования (например, так называемый язык командных файлов), или предназначены для автоматизации разработки больших программ (например, язык спецификации программ).
  • Служебные программы системы программирования. Со многими из этих программ мы уже познакомились в нашем курсе, например, сюда входят такие программы.
  • Текстовые редакторы, предназначенные для набора и исправления текстов программ на языках программирования.
  • Трансляторы (компиляторы) с одного языка на другой (например, программа Ассемблера транслирует с языка Ассемблер на язык объектных модулей).
  • Редакторы внешних связей, собирающие программы из модулей.
  • Загрузчики.
  • Отладчики, помогающие пользователям искать и исправлять ошибки в программах в диалоговом режиме.
  • Оптимизаторы, позволяющие автоматически улучшать программу, написанную на определённом языке.
  • Профилировщики, которые определяют, какой процент времени выполняется та или иная часть программы. Это позволяет выявить наиболее интенсивно используемые фрагменты программы и оптимизировать их (например, переписав на языке Ассемблера).
  • Библиотекари, которые позволяют создавать и изменять файлы-библиотеки процедур (например, библиотеки динамически загружаемых процедур DLL), файлы-библиотеки макроопределений и т.д.
  • Интерпретаторы, которые могут выполнять программы без перевода их на другие языки (точнее, с построчным переводом на машинный язык и последующим выполнением каждого такого переведённого фрагмента).
  • Информационное обеспечение системы программирования. Сюда относятся различные структурированные описания языков, служебных программ, библиотек модулей и т.п. Без хорошего информационного обеспечения современные системы программирования работать не могут. Каждый пользователь неоднократно работал с этой компонентой системы программирования, нажимая функциональную клавишу F1 или выбирая из меню пункт Help (Помощь).

Н
а рис. 11.1 показана общая схема прохождения программы пользователя через систему программирования. Программные модули пользователя на этом рисунке заключены в прямоугольники, а системные программы – в прямоугольники с закруглёнными углами.

На этом мы закончим описание состава системы программирования и перейдём к описанию характеристик исполняемых модулей.

11.2. Характеристики исполняемых модулей.


Модульная программа состоит из отдельных исполняемых модулей, которые могут обладать некоторыми специфическими характеристиками, к рассмотрению которых мы сейчас и перейдём.

11.2.1. Перемещаемые модули.


Программные модули, обладающие свойством перемещаемости, могут быть во время счёта программы перенесены в другое место оперативной памяти так, что это не повлияет на правильную работу этих модулей.

Рассмотрим пример, когда это свойство исполняемых модулей может оказаться полезным. На рис. 10.7 показан вид рабочего поля, на котором находятся процедуры с именами A и Delta. Предположим, что динамическому загрузчику необходимо разместить на этом поле новый модуль, скажем процедуру с именем C12, которая имеет длину 8000 байт. Видно, что загрузчику не удастся это сделать, не удалив с рабочего поля какую-нибудь процедуру, так как, несмотря на то, что 10000 байт рабочего поля свободны, но это свободное пространство разбито на две части, ни в одну из которых не войдёт процедура C12.

В том случае, если модуль Delta является перемещаемым, его можно сдвинуть так, чтобы объединить свободные участки рабочего поля и разместить на нём новую процедуру C12. Сдвиг модуля в оперативной памяти является по существу операцией пересылки массива и это заведомо более быстрая операция, чем удаление модуля с рабочего поля (ведь его потом, скорее всего, придётся вернуть обратно).

Рассмотрим, какими свойствами должен обладать модуль на Ассемблере, чтобы быть перемещаемым. При перемещении сегментов модуля на другое место памяти должны поменяться адреса начал этих сегментов в сегментных регистрах. Отсюда вытекает следующее ограничение на перемещаемый модуль: он не должен загружать значения сегментных регистров (как следствие он не может использовать более 4 сегментов). Следовательно, в нашей архитектуре модуль не может выполнять следующие команды
  • Команды пересылки вида mov SR,op2 , то есть загружать в сегментный регистр значение длинного регистра r16 или слова из памяти m16. Напомним, что параметр SR может принмать значения сегментных регистров DS, ES и SS.
  • Команды чтения из стека в сегментный регистр pop SR .
  • Команды дальнего возврата ret в свой собственный сегмент кода, т.е. выполнять дальний возврат внутри самого модуля.

Кроме того, такой модуль нельзя перемещать в другое место памяти во время выполнения системного вызова по команде int i8 , так как возврат из процелуры-обработчика прерывания производится по команде iret , которая, как мы знаем, тоже загружает кодовый сегментный регистр.

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

11.2.2. Повторно-выполняемые модули.


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

X dw 1

. . .

mov X,2

то программа будет повторно используемой только тогда, когда она восстанавливает первоначальное значение переменной X перед выходом из программы. В настоящее время это свойство программы не имеет большого значения, потому что появилось более сильное свойство модуля – быть повторно-входимым (реентерабельным).

11.2.3. Повторно-входимые (реентерабельные) модули.


Свойство исполняемого модуля быть реентерабельным (иногда говорят – параллельно используемым) является очень важным, особенно при написании системных программ. Модуль называется реентерабельным, если он допускает повторный вход в своё начало до выхода из этого модуля (для модулей на Ассемблере, как мы знаем, выход производится по команде возврата ret для процедур, по команде iret для обработчиков прерываний или по макрокоманде finish для основной программы).

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

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

Главное отличие реентерабельных программ от обычных рекурсивных процедур заключается именно в том, что при каждом входе в реентерабельную программу порождается новая текущая точка её выполнения и новое поле сохранения. Это позволяет продолжить выполнение реентерабельной программы с любой из этих нескольких текущих точек выполнения программы, восстановив значения всех регистров из поля сохранения этой точки программы.

Ниже перечислены основные свойства, которыми должен обладать модуль на Ассемблере, чтобы быть реентерабельным.
  • Модуль не меняет сегменты кода.
  • Модуль либо совсем не имеет собственных сегментов данных (т.е. использует сегмент данных другого модуля, на этот сегмент данных, как обычно, указывает значение регистра DS), либо при каждом входе получает новые копии своих сегментов данных.
  • При каждом входе в модуль он получает новый сегмент стека, пустой для основной программы и с копиями фактических параметров и адресом возврата для процедуры. Вообще говоря, этот сегмент стека является возможным местом и для расположения области сохранения модуля, хотя на современных ЭВМ область сохранения обычно размещается в так называемом пространстве ядра операционной системы, это место является защищённым от изменения со стороны программ обычных пользователей.

Реентерабельность является особенно важной при написании системных программ. Это следует из того, что если некоторая программа (например, компилятор с Ассемблера) является реентерабельной, то в оперативной памяти достаточно иметь только одну копию этой программы, которая может одновременно использоваться при компиляции любого числа программ на Ассемблере (отсюда второе название таких модулей – параллельно используемые).1

В современных ЭВМ большинство системных программ являются реентерабельными.