Макропроцессоры

Автор работы: Пользователь скрыл имя, 04 Апреля 2013 в 20:43, лекция

Описание работы

Макропроцессор — модуль системного ПО, позволяющий расширить возможности языка Ассемблера за счет предварительной обработки исходного текста программы.
Определение, которое показанное выше, не представляется удачным, так как оно говорит только о сокращении объема записи, а это лишь одна из возможностей обеспечиваемых Макропроцессором. Хотя Макропроцессоры являются обязательным элементом всех современных языков Ассемблеров, аналогичные модули (Препроцессоры) могут быть и для других языков, в том числе и для языков высокого уровня. Для одних языков (Pascal, PL/1) применение средств препроцессора является опционным, для других (C, C++) — обязательным.

Файлы: 1 файл

Макропроцессоры.docx

— 31.31 Кб (Скачать файл)

Макропроцессоры

Основные понятия

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

Определение, которое показанное выше, не представляется удачным, так  как оно говорит только о сокращении объема записи, а это лишь одна из возможностей обеспечиваемых Макропроцессором. Хотя Макропроцессоры являются обязательным элементом всех современных языков Ассемблеров, аналогичные модули (Препроцессоры) могут быть и для других языков, в том числе и для языков высокого уровня. Для одних языков (Pascal, PL/1) применение средств препроцессора является опционным, для других (C, C++) — обязательным.

Важно понимать, что Макропроцессор осуществляет обработку исходного  текста. Он «не вникает» в синтаксис  и семантику операторов и переменных языка Ассемблера, не знает (как правило) имен, употребляемых в программе, а выполняет только текстовые  подстановки. В свою очередь, Ассемблер  обрабатывает исходный текст, не зная, написан тот или иной оператор программистом «своей рукой» или  сгенерирован Макропроцессором. По тому, насколько Препроцессор (Макропроцессор) и Транслятор (Ассемблер) «знают»  о существовании друг друга, их можно  разделить на три категории:

u  Независимые. Препроцессор составляет отдельный программный модуль (независимую программу), выполняющую просмотр (один или несколько) исходного модуля и формирующую новый файл исходного модуля, поступающий на вход Транслятора (пример — язык C).

u  Слабосвязанные. Препроцессор составляет с Транслятором одну программу, но разные секции этой программы. Если в предыдущем случае Препроцессор обрабатывает весь файл, а затем передает его Транслятору, то в этом случае единицей обработки является каждый оператор исходного текста: он обрабатывается секцией Препроцессора, а затем передается секции Транслятора. (Пример — HLASM для S/390).

u  Сильносвязанные. То же распределение работы, что и в предыдущем случае, но Препроцессор использует некоторые общие с Транслятором структуры данных. Например, Макропроцессор может распознавать имена, определенные в программе директивой EQU и т.п.

(Пример — MASM, TASM).

Основные термины, связанные  с данными, обрабатываемыми Макропроцессором:

u  макровызов (или макрокоманда);

u  макроопределение;

u  макрорасширение.

Макровызов или макрокоманда или макрос — оператор программы, который подлежит обработке Макропроцессором (Макропроцессор обрабатывает не все  операторы, а только ему адресованные).

Макроопределение — описание того, как должна обрабатываться макрокоманда, макроопределение может находиться в том же исходном модуле, что  и макрокоманда или в библиотеке макроопределений.

Макрорасширение — результат  выполнения макровызова, представляющий собой один или несколько операторов языка Ассемблера, подставляемых  в исходный модуль вместо оператора  макровызова. Пример обработки макровызова  показан на рисунке.

Оператор макровызова  в исходной программе имеет тот  же формат, что и другие операторы  языка Ассемблера: В нем есть метка (необязательно), мнемоника и операнды. При обработке исходного текста если мнемоника оператора не распознается как машинная команда или директива, она считается макрокомандой и передается для обработки Макропроцессору.

 

Макроопределение описывает, как должна обрабатываться макрокоманда. Средства такого описания составляют некоторый Макроязык. Для Макропроцессоров 1-й и 2-й категорий средства Макроязыка могут быть достаточно развитыми. Для  Макропроцессоров 3-й категории средства Макроязыка могут быть довольно бедными, но в составе языка Ассемблера может быть много директив, применяемых  в макроопределениях (возможно, —  только в макроопределениях). В теле макроопределения могут употребляться  операторы двух типов:

 

u  операторы Макроязыка, которые не приводят к непосредственной генерации операторов макрорасширения, а только управляют ходом обработки макроопределения;

 

u  операторы языка Ассемблера (машинные команды и директивы), которые переходят в макрорасширение, возможно, с выполнением некоторых текстовых подстановок.

 

Поскольку макроопределение, обрабатывается перед трансляцией  или вместе с ней, макрокоманда, определенная в исходном модуле, может употребляться  только в этом исходном модуле и  «не видна» из других исходных модулей. Для повторно используемых макроопределений обычно создаются библиотеки макроопределений. В некоторых системах (например, z/OS) макрокоманды обеспечивают системные вызовы и существуют богатейшие библиотеки системных макроопределений.

 

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

 

Сравнение макросредств и  подпрограмм

 

Использование макросредств во многом подобно использованию  подпрограмм: в обоих случаях  мы сокращаем запись исходного текста и создаем повторно используемые фрагменты кода. (Например, в C/C++ вызов  псевдофункции неотличим от вызова функции.)

 

Принципиальные различия между подпрограммами и макросредствами:

 

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

 

u  Выполнение подпрограммы требует передачи управления с возвратом — команды типа CALL и RET, а команды макрорасширения включаются в общую последовательность команд программы (макровызовы выполняются быстрее).

 

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

 

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

 

Некоторые возможности Макроязыка

 

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

 

Заголовок макроопределения

 

Макроопределение должно как-то выделяться в программе, поэтому  оно всегда начинается с заголовка.

 

Заголовок имеет формат, подобный следующему:

 

имя_макрокоманды MACRO список формальных параметров

 

имя_макрокоманды является обязательным компонентом. При макровызове это имя употребляется в поле мнемоники оператора. Имена макроопределений, имеющихся в программе, должны быть уникальны. Обычно при распознавании макровызова поиск по имени макрокоманды ведется сначала среди макроопределений имеющихся в программе, а затем (если в программе такое макроопределение не найдено) — в библиотеках макроопределений. Таким образом, имя макрокоманды, определенной в программе, может совпадать с именем макрокоманды, определенной в библиотеке, в этом случае макрокоманда, определенная в программе, заменяет собой библиотечную.

 

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

 

В развитых Макроязыках возможны три формы задания параметров:

 

u  позиционная;

 

u  ключевая;

 

u  смешанная.

 

 

 

При использовании позиционной  формы соответствие фактических  параметров формальным определяется их порядковым номером. (Позиционная форма  всегда применяется для подпрограмм).

 

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

 

имя_параметра=значение_параметра

 

В таком же виде они описываются  и в списке формальных параметров, но здесь значение_параметра может опускаться. Если значение_параметра в списке формальных параметров не опущено, то это — значение по умолчанию. В макровызове параметры могут задаваться в любом порядке, параметры, имеющие значения по умолчанию, могут опускаться.

 

В смешанной форме первые несколько параметров подчиняются  правилам позиционной формы, а остальные  — ключевые.

 

В некоторых Макропроцессорах имена параметров начинаются с некоторого отличительного признака (например, амперсанда — &), чтобы Макропроцессор мог отличить «свои» имена (имена, подлежащие обработке при обработке макроопределения) от имен, подлежащих обработке Ассемблером. Для Макропроцессоров, которые мы отнесли к категории сильносвязанных такой признак может и не быть необходимым, так как такой Макропроцессор обрабатывает как свои имена, так и имена Ассемблера. В любом случае возникает проблема распознавания имени в теле макроопределения. Например, если макроопределение имеет формальный параметр &P, а в макровызове указано для него фактическое значение 'X', то как должна обрабатываться подстрока '&PA' в теле макроопределения? Должна ли эта подстрока быть заменена на 'XA' или оставлена без изменений?

 

Логика, которой следует  большинство Макропроцессоров в  этом вопросе, такова. &PA является именем в соответствии с правилами формирования имен. Поэтому оно не распознается как имя &P и остается без изменений. Если мы хотим, чтобы подстановка  в этой подстроке все-таки произошла, следует поставить признак, отделяющий имя параметра от остальной части  строки. Обычно в качестве такого признака используется точка — '.': '&P.A' заменяется на 'XA'.

 

Окончание макроопределения

 

Если у макроопределения есть начало (оператор MACRO), то у него, естественно, должен быть и конец. Конец  макроопределения определяется оператором MEND. Этот оператор не требует параметров. Макроопределение, взятое в «скобки» MACRO — MEND может располагаться в  любом месте исходного модуля, но обычно все макроопределения размещают  в начале или в конце модуля.

 

4

 

Локальные переменные макроопределения

 

Поскольку генерация макрорасширения  ведется по некоторому алгоритму, описанному в макроопределении, реализация этого  алгоритма может потребовать  собственных переменных. Эти переменные имеют силу только внутри данного  макроопределения, в макрорасширении  не остается никаких «следов» переменных макроопределения.

 

Переменные макроопределения могут использоваться двумя способами:

 

u  их значения могут подставляться вместо их имен в тех операторах макроопределения, которые переходят в макрорасширение;

 

u  их значения могут проверяться в условных операторах макроязыка и влиять на последовательность обработки.

 

При подстановке значений переменных макроопределения в макрорасширение  работают те же правила, что и при подстановки значений параметров.

 

Для сильносвязанных Макропроцессоров необходимости в локальных переменных макроопределения, вместо них могут использоваться имена программы (определяемые директивой EQU). Для сильносвязанных и независимых процессоров переменный макроопределения и имена программы должны различаться, для этого может применяться тот же признак, что и для параметров макроопределения.

 

Объявление локальной  переменной макроопределения может  иметь, например, вид:

 

имя_переменной LOCL начальное_значение (последнее необязательно)

 

Присваивание значений переменным макроопределения

 

Присваивание может производиться  оператором вида:

 

имя_переменной SET выражение

 

или

 

имя_переменной = выражение

 

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

 

Основной тип операций — строковые (выделение подстроки, поиск вхождения, конкатенация. etc.), так как обработка макроопределения состоит в текстовых подстановках.

 

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

 

Как обеспечить выполнение таких  операций? Можно предложить два варианта решения этой проблемы:

 

u  Ввести в оператор объявления переменной макроопределения определение ее типа. При выполнении операций должно проверяться соответствие типов.

 

u  Все переменные макроопределения имеют строковый тип, но при вычислении выражений автоматически преобразуются к типу, требуемому для данной операции (при таком преобразовании может возникать ошибка). Результат выражения автоматически преобразуется в строку.

Информация о работе Макропроцессоры