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


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



ЗНАЕТЕ ЛИ ВЫ?

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



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

Пусть макрос АRR Х,N предназначен для описания массива Х из N байтов:

ARR MACRO X, N

Х DB N DUP(?)

ENDM

Тогда, используя его, можно определить макрос АRR2, предназначенный для описания сразу двух массивов одного и того же размера;

АRR2 МАСRО Х1,Х2,К

АRR Х1,<К>

АRR Х2,<К>

ENDМ

При таком макроопределении макроподстановка для макроса АRR2 проходит в два этапа, например:

АRR2 А,В,20 à АRR A,< 20> à A DB 20 DUP(?)

ARR B,<20> В DВ 20 DUР(?)

Почему в теле макроса АRR2 при обращении в макросу АRR второй фактический параметр записывается в уголках? Дело в том, что если по смыслу первым и вторым параметрами макроса АRR2 могут быть только имена, то как третий параметр может быть указана достаточно сложная конструкция, например:

АRR2 А,В,<25 МОD 10>. Так вот, если бы вместо записи <К> использовалась просто запись К, тогда на первом этапе макроподстановки получилась бы макрокоманда АRR А,25 МОD 10 с четырьмя операндами, а не с двумя (напомним, что при макроподстановке уголки фактического параметра отбрасываются и что в макрокомандах параметры могут отделяться как запятыми, так и пробелами). При записи же <К> уголки заставляют рассматривать эту конструкцию как один параметр: АRR А, <25 МОD 10>.

Отметим, что в ЯА допускается вложенность макроопределений, например:

АRR2 МАСRО Х1,Х2,К

АRR МАСRО Х,N

Х DW N DUP (?)

ENDM

ARR X1,<K>

ARR X2,<K>

ENDM

Однако при этом надо учитывать следующее. Макрос АRR хотя и описан внутри макроса АRR2, не локализуется в АRR2, и к нему можно обращаться вне макроса АRR2. Но ассемблер работает так, что описание внутреннего макроса он "замечает" только при первом обращении к внешнему макросу. Поэтому обращаться к макросу АRR до обращения к макросу АRR2 нельзя:

АRR А,50;ошибка (имя ARR еще не описано)

АRR2 В,С,100

АRR D,60;можно (имя ARR уже описано)

 

Директива LOCAL

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

М MACRO

...

L :...

...

ENDM

и пусть в программе имеется два обращения к этому макросу. Тогда после макроподстановок мы получим следующую картину:

...

M à L :...

......

M à L :...

...

Как видно, в окончательном тексте программы появились две команды, помеченные одной и той же меткой L, а это ошибка. Почему так произошло? Дело в том, что имя L не является формальным параметром макроса и потому при макроподстановке ни на что не заменяется, а переносится в макрорасширение без всяких изменений. Вот и получается, что в окончательном тексте программы будет столько меток L, сколько было обращений к данному макросу. Как избежать этой ошибки? Возможный вариант - включить метку L в число параметров макроса и при обращении к макросу указывать различные фактические метки. Однако это плохое решение, поскольку метки, которыми метятся команды тела макроса, - это чисто внутреннее дело макроса, и для того, кто будет пользоваться этим макросом, нет никакого дела до этих меток, придумывать имена для таких внутренних меток - это лишняя работа. Учитывая это, в ЯА предложено иное, более удобное решение данной проблемы. Оно заключается в том, что после заголовка макроса (директивы МАСRО) надо указать специальную директиву макроязыка:

LOCAL v1,..., vk (k>=1),

где vi - имена, используемые в макроопределении (обычно это метки). Тогда при макроподстановке макрогенератор будет заменять эти имена на специальные имена вида??хххх, где хххх - четырехзначное шестнадцатеричное число, т. е. на имена??0000,??0001 и так далее до??РРРР. Правила такой замены следующие. Макрогенератор запоминает номер, который он использовал в последний раз; пусть это был номер n. Когда макрогенератор встречает обращение к макросу, в котором имеется директива LOCAL, то он ставит в соответствие именам, перечисленным в этой директиве, специмена с очередными номерами: специмя??(n+1) для v1, специмя??(n+2) для v2 и т. д., а затем при макроподстановке заменяет каждое вхождение vi на одно и то же специмя??(n+1). Когда макрогенератор встретит новое обращение к этому же или другому макросу, где есть директива LOCAL, то он будет уже использовать специмена с последующими номерами: n+k+1 и т. д. Поэтому в разных макрорасширениях появятся разные специмена, совпадений не будет. Рассмотрим конкретный пример. Опишем макрос, вычисляющий остаток от деления одного натурального числа на другое с помощью вычитания:

MD MACRO R1,R2;r1:=r1 mod r2 (r1,r2-регистры без знака)

LOCAL M, M1

M: CMP R1,R2;;while r1>=r2 do r1:=r1-r2

JMP M1

SUB R1,R2

JMP M

M1: ЕNDМ

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

R1→AX,R2→BX??0017: СМР АХ,ВХ

MD AX,BX ——————————> JB??0018

M→??0017, M1→??0018SUB AX,BX

JMP??0017

??0018:

R1→CX,R2→DX??0019: СМР СХ,DХ

MD CX,DX ——————————> JВ??001А

M→??0019, M1→??0010 SUB СХ,DХ

JMP??0019

??001А:

Таким образом, в разных макрорасширениях появляются разные метки, и тем самым проблема с одинаковыми метками снимается. Отметим, что директиву LOCAL можно указывать только после директивы МАСRО (но зато любое число раз) и нигде более и что директива LOCAL не переносится в макрорасширение. Кроме того, следует учитывать, что специмена??0017 и т. п. - это обычные имена, и, вообще говоря, мы можем их использовать сами, однако в силу их особой роли не рекомендуется применять эти имена в ином качестве.

 

Директива ЕХIТМ

Рассмотрим еще одну директиву макроязыка:

ЕХIТМ

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

Например, при макроопределении

A MACRO K

RЕРТ К

DB 0

ЕХIТМ

ENDM

DW?

ЕNDМ

Макрокоманда А 5 будет заменена на следующий текст:

DW 0

DW?

Здесь макрогенератор, создавая первую копию тела блока повторения, перенесет предложение DВ 0 в макрорасширение, а затем, встретив ЕХIТМ, полностью завершит обработку этого блока, но не покинет тело макроса - он "перескочит" за ближайшую директиву ЕNDM, т. е. на предложение DW?. Более содержательные примеры на директиву ЕХITМ будут приведены позже (они требуют знания условных директив). Пока лишь отметим, что эта директива ис­пользуется тогда, когда при выполнении некоторого условия надо досрочно (не доходя до ЕNDМ) прекратить макроподстановку или "раскрутку" блока повторения.

 



Поделиться:


Последнее изменение этой страницы: 2016-12-13; просмотров: 211; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

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