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

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

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

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

Файлы: 1 файл

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

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

 

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

 

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

 

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

 

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

 

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

 

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

 

Уникальные метки

 

В некоторых случаях операторы  машинных команд, имеющихся в макроопределении, должны быть помечены, например, для  того, чтобы передавать на них управление. Если применить для этих целей  обычную метку, то может возникнуть ошибочная ситуация. Если метка в  макроопределении имеет обычное  имя, и в модуле данная макрокоманда вызывается два раза, то будет сгенерировано  два макрорасширения, и в обоих будет метка с этим именем. Чтобы избежать ситуации неуникальности меток, в макроязыке создается возможность определять метки, для которых формируются уникальные имена. Обычно имя такой метки имеет тот же отличительный признак, который имеют параметры и переменные макроопределения. Каждую такую метку Макропроцессор заменяет меткой с уникальными именем.

 

Уникальное имя метки  может формироваться формате, подобном следующему:

 

&имя.nnnnnn

 

где — nnnnnn — число, увеличивающееся на 1 для каждой следующей уникальной метки.

 

Другой возможный способ формирования, например:

 

имя&SYSNDX

 

где SYSNDX — предустановленное  имя, имеющее числовое значение, начинающееся с 00001 и увеличивающееся на 1 для  каждой следующей уникальной метки.

 

Следующие операторы Макроязыка влияют на последовательность обработки  операторов макроопределения. В тех  или иных Макропроцессорах имеется  тот или иной набор таких операторов.

 

Оператор безусловного перехода и метки макроопределения

 

Возможный формат оператора:

 

MGO макрометка

 

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

 

Оператор условного перехода

 

Возможный формат оператора:

 

MIF условное_выражение макрометка

 

Если условное_выражение имеет значение «истина», обработка переходит на оператор, помеченный макрометкой, иначе обрабатывается следующий оператор макроопределения. Условные выражения формируются по обычным правилам языков программирования. В них могут употребляться параметры и переменные (локальные и глобальные) макроопределения, константы, строковые, арифметические и логические операции и, конечно же, операции сравнения.

 

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

 

Условные блоки 

 

Возможный формат оператора:

 

IF условное_выражение

 

операторы_макроопределения_блок1

 

ENDIF

 

ELSE

 

операторы_макроопределения_блок2

 

ENDIF

 

Если условное_выражение имеет значение «истина», обрабатываются операторы макроопределения от оператора IF до оператора ENDIF, иначе обрабатываются операторы макроопределения от оператора ESLE до оператора ENDIF. Как и в языках программирования блок ELSE — ENDIF не является обязательным.

 

Условные выражения описаны  выше. Обычно предусматриваются специальные  формы:

 

IFDEF имя

 

IFNDEF имя

 

проверяющие просто определено или не определено данное имя.

 

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

 

Операторы повторений

 

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

 

Как и в языках программирования, в Макроязыке может быть несколько  форм операторов повторения, приведем некоторые (не все) из возможных форм:

 

MDO выражение

 

блок_операторов_макроопределения

 

ENDMDO

 

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

 

MDOLIST переменная_макроопределения,

список_выражений

 

блок_операторов_макроопределения

 

ENDMDO

 

обработка блока операторов повторяется столько раз, сколько  элементов имеется в списке_выражений, при этом в каждой итерации переменной_макроопределения присваивается значение очередного элемента из списка_выражений.

 

MDOWHILE условное_выражение

 

блок_операторов_макроопределения

 

ENDMDO

 

обработка блока операторов повторяется до тех пор, пока значение условного_выражения — «истина».

 

Выдача сообщения

 

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

 

MOTE код_серьезности,код_ошибки,сообщение_об_ошибке

 

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

 

Должны индицироваться, как  минимум, следующие ситуации:

 

u  работа Макропроцессора может быть продолжена, по окончании ее может выполняться ассемблирование;

 

u  работа Макропроцессора может быть продолжена, но ассемблирование выполняться не может;

 

u  работа Макропроцессора не может продолжаться.

 

код_ошибки — числовой код, служащий, например, для поиска развернутого описания сообщений и действий при его возникновении в документе «Сообщения программы»

 

сообщение_об_ошибке — текст, печатаемый в листинге

 

Завершение обработки

 

Обработка макроопределения завершается при достижении оператора MEND. Однако, поскольку алгоритм обработки  макроопределения может разветвляться, должна быть предусмотрена возможность  выхода из обработки и до достижения конца макроопределения. Эта возможность  обеспечивается оператором MEXIT. Операндом  этого оператора может быть код_серьезности.

 

Комментарии макроопределения

 

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

 

Макрорасширения в листинге

 

Как уже неоднократно говорилось, макрорасширения для Ассемблера неотличимы от программного текста, написанного  программистом «своей рукой». Но программист, анализируя листинг программы, конечно, должен видеть макрорасширения и  отличать их от основного текста. Как  правило, директивы Ассемблера, управляющие печатью листинга предусматривают режим, при котором макрорасширение не печатается в листинге, а печатается только макрокоманда и режим, при котором в листинге печатается и макрокоманда, и ее макрорасширение, но операторы макрорасширения помечаются каким-либо специальным символом.

 

Структуры данных Макропроцессора

 

 

 

Таблица макроопределений, строго говоря, не таблица, а просто массив строк, в который записываются тексты всех макроопределений (от оператора MACRO до оператора MEND), найденных в обрабатываемом модуле.

 

Таблица имен макроопределений содержит имена макроопределений и  указатель на размещение текста макроопределения в таблице макроопределений, как  показано на рисунке.

 

 

 

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

 

Для обработки каждого  макровызова создаются:

 

u  Таблица параметров, содержащая информацию о параметрах макроопределения.

 

u  Таблица локальных переменных, содержащая информацию о локальных переменных макроопределения.

 

Структура этих таблиц —  такая же, как и таблицы глобальных переменных, эти две таблицы могут  быть объединены в одну таблицу параметров и локальных переменных.

Алгоритм работы Макропроцессора

 

Очевидно, что когда Макропроцессор обрабатывает макровызов, он уже должен «знать» макроопределение данной макрокоманды. Для обеспечения этого таблицы  макроопределений и имен макроопределений должны быть созданы до начала обработки  макровызовов. Поэтому Макропроцессор должен состоять из двух проходов, на первом проходе строятся таблицы макроопределений и имен макроопределений, а на втором осуществляется обработка макровызовов. Если макроопределения сосредоточены  в начале исходного модуля, то Макропроцессор может быть и однопроходным. Ниже мы приводим алгоритм работы 2-проходного Макропроцессора, при этом мы исходим  из следующих предпосылок:

 

u  наш Макропроцессор является независимым от Ассемблера;

 

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

 

u  операторы Макроязыка включают в себя: MACRO, MEND, MEXIT, MNOTE, LOCL, GLBL, SET, MGO, MIF;

 

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

 

Библиотеки макроопределений

 

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

 

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

 

Один из таких алгоритмов следующий.

 

Анализ мнемоники производится на 1-м проходе Ассемблера, все  операторы, не распознанные как операторы  языка Ассемблера, считаются макрокомандами и для них создаются строки в Таблице имен макроопределений.

 

Если для такой макрокоманды макроопределение еще не найдено, поле ссылки на Таблицу макроопределений остается пустым.

 

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

 

В конце 1-го прохода просматривается  Таблица имен макроопределений. Если в таблице находятся имена  с пустыми ссылками на Таблицу  макроопределений, соответствующее  макроопределение ищется в библиотеках. Если макроопределение найдено в  библиотеке, его текст переписывается в Таблицу макроопределений и  присваивается значение ссылке в  соответствующей строке Таблицы  имен макроопределений.

 

Если после этого в  Таблице имен макроопределений остаются имена с пустыми ссылками, это  свидетельствует об ошибках в  программе.

 

Вложенные макровызовы.

Вложенные макроопределения

 

Можно ли употреблять макроопределения внутри макроопределений? Можно ли употреблять макровызовы вызовы внутри макроопределений? Представленные выше алгоритмы делать этого не позволяют. Тем не менее, можно построить  такие алгоритмы Макропроцессора, которые это позволять будут. Эти алгоритмы в любом случае будут довольно «затратными», то есть, требующими много ресурсов — процессорного  времени и памяти. «Классические» алгоритмы, создававшиеся в условиях хронического дефицита памяти, были очень  ограничены.

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