Основные функции макропроцессоров 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Основные функции макропроцессоров



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

4.1.1. Макроопределения и макрорасширения

На рис. 4.1 изображен пример программы для УУМ/ДС, в которой используются макроинструкции. Эта программа выполняет те же функции и имеет ту же логику, что и фрагмент программы, изображенной на рис. 2.5. Изменен только способ нумерации предложений.

В этой программе определены и используются две макроинструкции RDBUFF и WRBUFF. Функции и логика макроопределения RDBUFF те же, что и у подпрограммы RDREG, изображенной на рис. 2.5; макроопределение WRBUFF аналогично подпрограмме WRREG. Эти макроопределения находятся в исходной программе непосредственно после предложения START.

В них используются две новые директивы ассемблера - MACRO и MEND. Первое предложение MACRO (строка 10) идентифицирует начало макроопределения. Текст в поле метки (RDBUFF)

5 COPY START 0 КОПИРОВАНИЕ ФАЙЛА

10 RDBUFF MACRO &INDEV,&BUFADR,&RECLTH

15.

20. МАКРОС ДЛЯ ЧТЕНИЯ В БУФЕР

25.

30 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА

35 CLEAR А

40 CLEAR S

45 +LDT #4096 УСТАНОВКА МАКС. ДЛИНЫ ЗАПИСИ

50 TD =X'&INDEV' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА

55 JEQ *-3 ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ

60 RD =X'&INDEV' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А

65 COMPR A,S ПАРОВЕРКА НА КОНЕЦ ЗАПИСИ

70 JEQ *+11 ВЫХОД ИЗ ЦИКЛА ЕСЛИ КОНЕЦ ЗАПИСИ

75 STCH &BUFADR,X ЗАПИСЬ СИМВОЛА В БУФЕР

80 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ

85 JLT *-19 ДЛИНЫ ЗАПИСИ

90 STX &RECLTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ

95 MEND

100 WRBUFF MACRO &OUTDEV,&BUFADR,&RECLTH

105.

110. МАКРОС ДЛЯ ЗАПИСИ ИЗ БУФЕРА

115.

120 CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА

125 LDT &RECLTH

130 LDCH &BUFADR,X ВЫБОРКА СИМВОЛА ИЗ БУФЕРА

135 TD =X'&OUTDEV' ПРОВЕРКА ГОТОВНОСТИ УСТРОЙСТВА

140 JEQ *-3 ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ

145 WD =X'&OUTDEV' ЗАПИСЬ СИМВОЛА

150 TIXR T ЦИКЛ ПОКА ВСЕ СИМВОЛЫ НЕ БУДУТ

155 JLT *-14 ЗАПИСАНЫ

160 MEND

165.

170. ОСНОВНАЯ ПРОГРАММА

175.

180 FIRST STL RETADR СОХРАНЕНИЕ АДРЕСА ВОЗВРАТА

190 CLOOP RDBUFF F1,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 @RETADR

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.1. Использование макросов в программе для УУМ/ДС.

 

(RDBUFF) является???????????????????????????. В поле операнда находятся имена формальных параметров макроопределения. В нашем макроязыке имена всех формальных параметров начинаются спецсимволом & (амперсанд), что позволяет осуществлять замену формальных параметров на фактические в процессе макрогенерации. Имя и параметры макроса определяют шаблон или прототип используемой программистом макроинструкции. После директивы MACRO следуют предложения, составляющие тело макроопределения (строки с 15 по 90). Именно эти предложения и будут порождены в процессе макрогенерации. Директива ассемблера MEND (строка 95) является признаком конца макроопределения. Определение макроса WRBUFF (строки с 100 по 160) имеет аналогичную структуру.

Основная программа начинается со строки 180. Предложение в строке 190 является предложением макроинициализации. Оно определяет имя макроинструкции, которая должна быть инициализирована, и аргументы (фактические параметры), которые должны быть использованы в процессе макрогенерации при порождении макрорасширения. (Предложение макроинициализации часто называют также предложением макровызова или просто макровызовом. Для того чтобы избежать путаницы с предложениями вызова процедур и подпрограмм, мы предпочитаем использовать термин "макроинициализация". Как мы увидим, процесс макроинициализации совершенно отличен от процесса вызова подпрограммы.)

Читатель должен сравнить логику головной программы на рис. 4.1 с логикой программы на рис. 2.5, помня о схожести функций RDBUFF и RDREG, WRBUFF и WRREG.

Программа на рис. 4.1 может быть подана на вход макропроцессора. На рис. 4.2 изображена результирующая программа. Определения макроинструкций в ней отсутствуют, поскольку после порождения макрорасширений они уже не нужны. Каждое предложение макроинициализации превратилось в предложения видоизмененного тела макроопределения, в котором формальные параметры, описанные в макропрототипе (заголовке макроопределения), заменены аргументами предложения макроинициализации. Между аргументами и параметрами имеется позиционное соответствие: первый аргумент в предложении макроинициализации соответствует первому параметру в макропрототипе и т. д. Например, при расширении предложения макроинициализации в строке 190 параметр &INDEV всюду, где он встречается в теле макроопределения, заменен на аргумент FI. Аналогично &BUFADR заменен на BUFFER и &RECLTH заменен на LENGTH.

Строки 190а -1901 представляют собой полное расширение инструкции макроинициализации в строке 190. Строки комментариев внутри тела макроопределения удалены, однако комментарии внутри предложений языка остались. Обратите внимание,

5 COPY START 0 КОПИРОВАНИЕ ФАЙЛА

180 FIRST STL RETADR ЗАПОМИНАНИЕ АДРЕСА ВОЗВРАТА

190.CLOOP RDBUFF F1,BUFFER,LENGTH ЧТЕНИЕ ЗАПИСИ В БУФЕР

190а CLOOP CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА

190b CLEAR А

190c CLEAR S

190d +LDT #4096 УСТАНОВКА МАКС. ДЛИНЫ ЗАПИСИ

190e TD =X'F1' ПРОВЕРКА ВХОДНОГО УСТРОЙСТВА

190f JEQ *-3 ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ

190g RD =X'F1' ЧТЕНИЕ СИМВОЛА В РЕГИСТР А

190h COMPR A,S ПРОВЕРКА ОКОНЧАНИЯ ЗАПИСИ

190i JEQ *+11 ВЫХОД ПО КОНЦУ ЗАПИСИ

190j STCH BUFFER,X ЗАПИСЬ СИМВОЛА В БУФЕР

190k TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ

190l JLT *-19 ДЛИНЫ ЗАПИСИ

190m STX LENGTH СОХРАНЕНИЕ ДЛИНЫ ЗАПИСИ

195 LDA LENGTH ПРОВЕРКА НА КОНЕЦ ФАЙЛА

200 COMP #0

205 JEQ ENDFIL ВЫХОД ПО КОНЦУ ФАЙЛА

210 WRBUFF 05, BUFFER,LENGTH ЗАПИСЬ БУФЕРА

210a CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА

210b LDT LENGTH

210c LDCH BUFFER,X ЧТЕНИЕ СИМВОЛА ИЗ БУФЕРА

210d TD =X'05' ПРОВЕРКА ВЫХОДНОГО УСТРОЙСТВА

210e JEQ *-3 ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ

210f WD =X'05' ЗАПИСЬ СИМВОЛА

210g TIXR T ЦИКЛ ПОКА ВСЕ СИМВОЛЫ НЕ БУДУТ

210h JLT *-14 ЗАПИСАНЫ

215 J CLOOP ЦИКЛ

220.ENDFIL WRBUFF 05,EOF,THREE ЗАНЕСЕНИЕ МАРКЕРА КОНЦА ФАЙЛА

220a ENDFIL CLEAR X ОЧИСТКА СЧЕТЧИКА ЦИКЛА

220b LDT THREE

220c LDCH EOF,X ЧТЕНИЕ СИМВОЛА ИЗ БУФЕРА

220d TD =X'05' ПРОВЕРКА ВХОДНОГО УСТРОЙСТВА

220e JEQ *-3 ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ

220f WD =X'05' ЗАПИСЬ СИМВОЛА

220g TIXR T ЦИКЛ ПОКА ВСЕ СИМВОЛЫ НЕ БУДУТ

220h JLT *-14 ЗАПИСАНЫ

225 J @RETADR

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. с макрорасширениями.

 

что сами предложения макроинициализации вставлены как строки комментария. Они служат для напоминания об исходных предложениях, написанных программистом. Метка предложения макроинициализации (CLOOP) оставлена в качестве метки первого предложения сгенерированного макрорасширения. Это позволяет программисту использовать макроинструкции аналогично другим инструкциям языка ассемблера. Расширение предложений макроинициализации в строках 210 и 220 осуществляется аналогично. Заметьте, что в двух макроинициализациях макроса WRBUFF заданы разные аргументы и в результате получены различные расширения.

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

Сравнение расширенной программы на рис. 4.2 с программой на рис. 2.5 показывает наиболее существенные различия между макроинициализацией и вызовом подпрограммы. В программе на рис. 4.2 предложения из тела макроса WRBUFF сгенерированы дважды: строки 210а-210h и 220а-220h. В программе на рис. 2.5 соответствующие предложения имеются лишь в единственном экземпляре в подпрограмме WRREG (строки 210-240). Это является общим правилом. Предложения, составляющие расширение макроса, генерируются (и соответственно ассемблируются) каждый раз, когда соответствующий макрос инициализируется. Предложения подпрограммы имеются лишь в единственном экземпляре независимо от того, сколько раз эта подпрограмма вызывается.

Заметьте также, что наши макроинструкции были написаны таким образом, что тело макроопределения не содержало меток. На рис. 4.1 в строке 140 находится предложение "JEQ*-3", в строке 155-предложение "JLT*-14". Соответствующими предложениями в подпрограмме WRREC (рис. 2.5) являются "JEQ WLOOP" и "JLT WLOOP", где WLOOP - метка TD инструкции, проверяющей состояние устройства вывода. Если бы эта метка была в строке 135 тела макроопределения, она была бы сгенерирована дважды: в строках 210Ь и 220d (рис. 4.2). Это привело бы к ошибке (дважды определенная метка) во время работы ассемблера. Для того чтобы избежать дублирования меток, мы исключили их из тел наших макроопределений.

Использование предложений, подобных "JLT *-14", считается признаком плохого стиля программирования. Их применение отчасти может быть оправданно внутри тела макроопределения, однако и это можно считать плохим стилем, увеличивающим вероятность появления ошибок. В разд. 4.2.2 мы обсудим, как можно избежать подобных конструкций



Поделиться:


Последнее изменение этой страницы: 2017-02-17; просмотров: 123; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.138.116.20 (0.014 с.)