
- •Структура компиляторов. Общая схема работы компилятора.
- •Порядок обработки программ: Компиляция или ассемблирование, компоновка, отладка. Средства обработки программ: редакторы, компиляторы, ассемблеры, отладчики.
- •Основные функции библиотек программ и их составы.
- •Команды пересылки, сравнения и сдвига денных в ассемблерных программах.
- •Арифметические команды в ассемблерных программах; разновидности и примеры команд.
- •Команды передачи управления в ассемблерных программах: условные и безусловные переходы, циклы.
- •Загрузчики. Основные функции загрузчика.
-
Основные функции библиотек программ и их составы.
Библиотеки подпрограмм составляют существенную часть систем программирования. Наряду с дружественностью пользовательского интерфейса, состав доступных библиотек подпрограмм во многом определяет возможности системы программирования и ее позиции на рынке средств разработки программного обеспечения. Библиотеки подпрограмм входили в состав средств разработки, начиная с самых ранних этапов их развития. Даже когда компиляторы еще представляли собой отдельные программные модули, они уже были связаны с соответствующими библиотеками, поскольку компиляция так или иначе предусматривает связь программ со стандартными функциями исходного языка. Эти функции обязательно должны входить в состав библиотек.
С точки зрения системы программирования библиотеки подпрограмм состоят из двух основных компонентов. Это собственно файл (или множество файлов) библиотеки, содержащий объектный код, и набор файлов описаний функций, подпрограмм, констант и переменных, составляющих библиотеку. Описания оформляются на соответствующем входном языке (например, для языка С или С++ это будет набор заголовочных файлов). Иногда эти файлы могут быть совмещены (например, в системе программирования Turbo Pascal стандартные библиотеки представлены в виде объектных файлов специального формата — TPU — Turbo Pascal Units). Кроме того, в современных системах программирования в состав библиотеки входит также описание ее на естественном языке в виде файла подсказок и справок. Набор файлов описания библиотеки служит для информирования компилятора о составе входящих в библиотеку функций. Обрабатывая эти файлы, компилятор получает всю необходимую информацию о составе библиотеки с точки зрения входного языка программирования. Эти файлы предназначены только для того, чтобы избавить разработчика от необходимости постоянного описания библиотечных функций, подпрограмм, констант и переменных.
В состав системы программирования может входить большое количество разнообразных библиотек. Среди них всегда можно выделить основную библиотеку содержащую обязательные функции входного языка программирования. Т акая библиотека называется обычно стандартной библиотекой языка. Эта библиотека всегда используется компилятором, поскольку без нее разработка программ на данном входном языке невозможна. Все остальные библиотеки необязательны и подключаются к результирующей программе только по прямому указанию разработчика.
В процессе развития систем программирования состав библиотек постоянно расширялся. В них включалось все большее и большее число функций. Это было вызвано тем, что система программирования, предоставляющая пользователю более широкий выбор библиотечных функций, получала лучшие позиции на рынке средств разработки программного обеспечения. Сами по себе библиотеки подпрограмм и функций, созданных для того или иного языка, также становились товаром на рынке средств разработки. Этот естественный процесс продолжается до сих нор, и чем длиннее история существования того или иного языка программирования, тем шире диапазон существующих для него библиотек.
Системы программирования для некоторых языков продолжают существовать во многом благодаря тому, что для них создан мощный аппарат библиотечных функций. Так, язык FORTRAN существует благодаря широчайшему набору функций для работы с математическими и физическими процессами, а язык COBOL благодаря набору функций из финансовой сферы.
В ходе развития систем программирования принципы создания и использования библиотечных функций претерпели мало изменений. Принципиально новые возможности предоставили только современные ОС, которые позволили подключать к результирующим программам не статические, а динамические библиотеки.
Статические библиотеки подпрограмм
Статические библиотеки подпрограмм и функций представляют собой часть объектного кода, которая встраивается (подключается) к резуль тирующей программе на этапе ее разработки.
Все статические библиотеки подключаются к результирующей программе один раз на этапе ее создания, после чего они являются ее неотъемлемой частью. Код статических библиотек входит в состав исполняемого файла программы точно так же, как и объектный код, созданный компилятором на основе исходного текста программы. При выполнении программы нет никакого различия между объектным кодом, построенным на основании исходного текста, созданного разработчиком, и объектным кодом библиотеки.
Объектный код статической библиотеки подключается компоновщиком к результирующей программе при создании исполняемого модуля. Поэтому но своей структуре статическая библиотека мало чем отличается от обычных объектных файлов, порождаемых компилятором. Чаще всего система программирования хранит объектный код входящих в ее состав библиотек в некотором упакованном виде. При подключении библиотеки к исполняемому файлу компоновщик распаковывает ее код и встраивает его в общий объектный код результирующей программы в обычном порядке.
Будучи один pas созданной с использованием статических библиотек, результирующая программа в дальнейшем уже никак не зависит от изменений в этих библиотеках, а также от их наличия в вычислительной системе, где она будет выполняться.
Весь необходимый объектный код уже входит в состав такой программы. В этом очевидное преимущество использования статических библиотек. В то же время статические библиотеки обладают двумя недостатками, один из которых является весьма существенным.
Во-первых, при наличии ошибки в библиотеке она будет проявляться во всех программах, которые используют эту библиотеку , а после ее исправления все такие программы нужно будет построить (пересобрать) заново с использованием обновленной библиотеки. Конечно, если учесть, что в современных системах программирования все новые библиотеки появляются только после тщательной всесторонней отладки, этим недостатком можно пренебречь.
Во-вторых, поскольку объектный код статических библиотек встраивается в исполняемый файл, это ведет к увеличению объема результирующей программы. В современных прикладных программах более 50 % объектного кода может составлять код из файлов библиотек. При наличии многих программ, использующих код одной и той же библиотеки, это ведет к неэффективному использованию как места для хранения исполняемых файлов программ, так и оперативной памяти вычислительной системы во время их выполнения. В особенности это относится к системным библиотекам — библиотекам ОС, которые используются если не всеми, то очень многими программами.
Именно второй недостаток статических библиотек послужил толчком к созданию другого типа библиотек подпрограмм и функций динамически загружаемых (или просто динамических) библиотек.
Динамические библиотеки подпрограмм
Динамические (динамически загружаемые) библиотеки подключаются к результирующей программе в момент ее выполнения. В этом основное отличие динамических библиотек от обычных статических библиотек.
Возможны два основных варианта загрузки динамических библиотек при выполнении результирующей программы. В первом варианте динамическая библиотека загружается в оперативную память компьютера сразу же, как только начинает выполняться программа, использующая данную библиотеку, вне зависимости от того, будет ли выполняться обращение к функциям библиотеки или нет. Во втором варианте библиотека загружается в оперативную память только тогда, когда происходит непосредственное обращение к одной из ее подпрограмм или функций. Соответственно, существует два варианта освобождения памяти, занимаемой динамической библиотекой: она освобождается либо только по завершении выполнения всей программы, либо по команде основной программы, сигнализирующей о том, что данная библиотека более использоваться не будет.
Второй вариант является более предпочтительным с точки зрения экономии объема занимаемой оперативной памяти. Но он сложнее в реализации и требует указаний разработчика программы, поскольку только разработчик может явно определить моменты выполнения программы, которые требуют загрузки в память той или иной библиотеки или, наоборот, освобождения памяти, когда библиотека более не будет использоваться. Первый вариант менее экономично расходует оперативную память, но проще в реализации, поскольку компоновщик сам может определить переченьвсех используемых в программе библиотек и обеспечить загрузку их в память и момент начала выполнения программы. Современные системы программирования предусматривают, как правило, оба варианта работы с динамически загружаемыми библиотеками — решение о том, какой вариант будет использован, принимает разработчик программы. В принципе, одна программа может предполагать различные варианты работы с различными библиотеками выбор зависит от объема кода библиотеки и от частоты обращений к ней.
За загрузку динамических библиотек в оперативную память, освобождение памяти, занятой динамическими библиотеками, а также за связь кода и данных библиотек с кодом и данными исполняемой программы отвечает динамический загрузчик , который входит в состав ОС. Он же обеспечивает повторное использование кода динамических библиотек. Повторное использование кода заключается в том, что, если две различные программы обращаются к одной и той же динамической библиотеке, нет необходимости загружать ее объектный код в оперативную память дважды достаточно обеспечить доступ обеим программам к одной и той же копии объектного кода при условии разделения данных.
Формат файлов динамических библиотек может быть различным. Как правило, он строго определяется требованиями соответствующей ОС и близок к формату исполняемых файлов. Как и статические библиотеки, динамические библиотеки предусматривают описание входящих в них функций в виде текста па соответствующем входном языке, чтобы дать информацию о них компилятору в ходе обработки исходного текста программы и избавить разработчика от создания таких описаний. Но для динамических библиотек компилятор не включает в код программы обращения к функциям, как он это делает для статических библиотек. Вместо этого в код вставляются вызовы соответствующих функций ОС, обеспечивающих обращение к коду динамической библиотеки, если связь с библиотекой осуществляется но первому варианту работы. Если же связь с динамической библиотекой осуществляется но второму варианту, то разработчик сам должен организовать вызов соответствующих функций ОС в исходном коде.
Преимущества динамических библиотек очевидны — они не требуют включения в результирующую программу объектного кода часто используемых функций, чем существенно сокращают ее объем. Конечно, динамические библиотеки требуют наличия в ОС специального механизма, позволяющего подключать часть объектного кода непосредственно но ходу выполнения программы. Однако для современных ОС, выполняющихся в вычислительных системах, которые поддерживают широкий набор методов адресации, это не является проблемой (14,15, 62].
Недостатки динамически загружаемых библиотек заключаются в том, что результирующие программы оказываются связаны с объектным кодом, непосредственно не входящим в их состав. Ъгда для выполнения такой программы обязательно требуется наличие всех используемых ею библиотек в составе вычислительной системы, где эта программа выполняется. Кроме того, логика работы резулвирующей программы становится зависимой от кода всех входящих в нее библиотек. Изменение библиотеки, которое может происходить независимо от разработчиков программы, может повлиять на функционирование самой программы. Т акое развитие событий порой оказывается неожиданным для пользователя.
мощыо специальных системных функций, предоставляемых ОС. Как правило, для удобства работы с ними эти функции входят в состав одной или нескольких динамически загружаемых библиотек, поставляемых ОС. Кроме того, в составе ОС обычно предусмотрен специальный набор наиболее часто используемых ресурсов интерфейса, называемых системными. Пользователь не должен разрабатывать и включать в состав результирующей программы такой ресурс он может воспользоваться ресурсом, входящим в состав ОС. Примерами системных ресурсов являются: внешний вид текста системных сообщений (системный шрифт или фонт), основной фон окон и меню прикладных программ, внешний вид наиболее употребительных органов управления (кнопок, списков и т. п.).
В каком бы виде и формате ни хранились ресурсы в резуль тирующей программе, порядок их создания практически всегда один и тот же: сначала создается описание ресурсов пользовательского интерфейса на входном языке описания ресурсов, затем оно обрабатывается компилятором ресурсов , входящим в состав системы программирования. После этого компоновщик подключает ресурсы к исполняемому файлу результирующей программы, или оформляет их в виде динамически загружаемой библиотеки, или оставляет в виде отдельного файла ресурсов.
Язык описания ресурсов — это, как правило, простой язык, построенный на основе регулярной грамматики. 11о строить описания ресурсов в таком виде неэффективно, так как любому разработчику внешний вид интерфейса программы удобнее формировать в виде графических образов. Это тем более важно, поскольку часто интерфейс создают не программисты, а дизайнеры. Поэтому современные системы программирования имеют в своем составе графические средства редактирования ресурсов пользовательского интерфейса. Эти средства позволяют создавать интерфейс в виде графических образов, на основе которых потом строится его описание на языке описания ресурсов. В системах программирования, предлагающих средства быстрой разработки приложений (RAD), средства разработки графического интерфейса позволяют также создать простейший шаблон исходного кода для работы с этим интерфейсом.
Преимущество использования ресурсов заключается в том, что пользовательский интерфейс результирующей программы можно проектировать, создавать и изменять независимо от логики работы самой программы. Эту работу можно поручить дизайнерам, в то время как исходный код создают программисты. Например, чтобы перевести программу на новый язык1, часто бывает достаточно перевести на этот язык все текстовые сообщения и строковые элементы форм, и это гораздо удобнее выполнять, если они находятся отдельно, а не внутри исходного кода.