Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Определение макроса через макросСодержание книги
Поиск на нашем сайте
Как известно, процедура имеет право обращаться к другой процедуре. Аналогично, при описании одного макроса можно ссылаться на другой макрос. В частности, допускается и обращение макроса к самому себе, т. е. разрешены рекурсивные макросы. Однако рекурсивные макросы встречаются на практике крайне редко, поэтому рассмотрим лишь пример нерекурсивного обращения одного макроса к другому и возникающие при этом проблемы. Пусть макрос А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; просмотров: 235; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.128.95.219 (0.007 с.) |