assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 69
Текст из файла (страница 69)
Это даетвозможность сократить объем исходного кода путем удаления неиспользуемыхкоманд.Директива GOTO имя_метки переводит процесс генерации макроопределенияв другое место, прекращая тем самым последовательное разворачивание строк макроопределения. Метка, на которую передается управление, имеет специальныйформат::имя_меткиПримеры применения этих директив будут приведены далее.Директивы компиляции по условиюДирективы компиляции по условию предназначены для выборочной трансляциифрагментов программного кода.
Это означает, что в макрорасширение включаются не все строки макроопределения, а только те, которые удовлетворяют определенным условиям. Какие конкретно условия должны быть проверены, определяетсятипом условной директивы. Введение в язык ассемблера этих директив значительнорасширяет его возможности. Всего имеются 10 типов условных директив компиляции. Их логично попарно объединить в четыре группы:Директивы условной компиляции309* IF и IFE — условная трансляция по результату вычисления логического выражения;Я IFDEF и IFNDEF — условная трансляция по факту определения символическогоимени;Я IFB и IFNB — условная трансляция по факту определения фактического аргумента при вызове макрокоманды;II IFIDN, IFIDNI, IFDIF и IFDIFI — условная трансляция по результату сравнения строксимволов.Условные директивы компиляции имеют общий синтаксис и применяютсяв составе следующей синтаксической конструкции:IFxxxлогическое_выражение_или_аргументыфрагмент_программы_1ELSEфрагмент_программы_2ENDIFЗаключение некоторых фрагментов текста программы (фрагмент_программы_1и фрагмент_программы_2) между директивами IFxxx, ELSE и ENDIF приводит к ихвыборочному включению в объектный модуль.
Какой именно из этих фрагментовбудет включен в объектный модуль, зависит от конкретного типа условной директивы, задаваемого значением ххх, и значения условия, определяемого операндом(операндами) условной директивы логическое_выражение_или_аргумент(ы).Директивы IF и IFEСинтаксис директив IF и IFE следующий:IF(E)логическое_выражениефрагмент_программы_1ELSEфрагмент_программы_2ENDIFОбработка этих директив макроассемблером заключается в вычислении логического выражения и включении в объектный модуль первого (фрагмент_программы_1) или второго (фрагмент_программы_2) фрагмента программы в зависимостиот того, в какой директиве (IF или IFE) это выражение встретилось.ш Если в директиве IF логическое выражение истинно, то в объектный модульпомещается первый фрагмент программы.
Если логическое выражение ложно,то при наличии директивы ELSE в объектный код помещается второй фрагментпрограммы. Если же директивы ELSE нет, то вся часть программы между директивами IF и ENDIF игнорируется, и в объектный модуль ничего не включается.Кстати сказать, понятие'истинности и ложности значения логического выражения весьма условно. Ложным оно будет считаться, если его значение равнонулю, а истинным — при любом значении, отличном от нуля.• Директива IFE аналогично директиве IF анализирует значение логического выражения.
Но теперь для включения первого фрагмента программы в объектный модуль требуется, чтобы логическое выражение было ложным.Директивы IF и IFE очень удобно использовать для изменения текста программы в зависимости от некоторых условий. К примеру, составим макрос для опре-310Глава 14. Макросредства языка ассемблераделения в программе области памяти длиной не более 50 и не менее 10 байт (листинг 14.4).Листинг 14.4.
Использование условных директив IF и IFE<1><2>;prg_14_4.asmmasm<4>stack<3><5><6><7><8><9><20><21><22><23><24><25><26><27>modelsmall256def_tab_50 macroif len GE 50GOTO exitendifif len LT 10:exitEXITMendifrept lendb 0endmendm.datadef_tab_50 15def_tab_50 5.codemain:mov ax,@datamov ds.axexit:mov ax,4c00hint 21hend mainlenВведите и оттранслируйте листинг 14.4. Не забывайте о том, что условные директивы действуют только на шаге трансляции, и поэтому результат их работыможно увидеть лишь после макрогенерации, то есть в листинге программы.
В немвы обнаружите, что в результате трансляции строка 18 листинга 14.4 развернетсяв пятнадцать нулевых байтов, а строка 19 оставит макрогенератор совершенно равнодушным, так как значение фактического операнда в строках б и 9 будет ложным.Обратите внимание на то, что для обработки реакции на ложный результат анализа в условной директиве мы использовали макродирективы ЕХПМ и GOTO. Наверное, в данном случае можно было бы составить более оптимальный вариант макрокоманды для резервирования некоторого пространства памяти в сегменте данных,а данный способ выбран, исходя из учебных целей.Другой интересный и полезный вариант применения директив IF и IFE — отладочная печать.
Суть здесь в том, что в процессе отладки программы почти всегдавозникает необходимость динамически отслеживать состояние определенных программно-аппаратных объектов, в качестве которых могут выступать переменные,регистры процессора и т. п. После этапа отладки отпадает необходимость в такихдиагностических сообщениях. Для их устранения приходится корректировать исходный текст программы, после чего подвергать ее повторной трансляции. Но естьболее изящный выход. Можно определить в программе некоторую переменную, к примеру debug, и использовать ее совместно с условными директивами IF или IFE:<2>debugequ IДирективы условной компиляции<4>311.code<5><б><7><8><9>if debug;любые команды и директивы ассемблера;(вывод на печать или монитор)endifНа время отладки и тестирования программы вы можете заключить отдельныеучастки кода в своеобразные операторные скобки в виде директив IF и ENDIF (строки 6-9 последнего фрагмента), реагирующие на значение логической переменнойdebug.
При значении debug = 0 транслятор полностью проигнорирует текст внутриэтих условных операторных скобок; при debug = 1, наоборот, будут выполнены вседействия, описанные внутри них.Директивы IFDEF и IFNDEFСинтаксис директив IFDEF и IFNDEF следующий:IF(N)DEFсимволическое_имяфрагмент_программы_1ELSEфрагмент_программы_2ENDIFДанные директивы позволяют управлять трансляцией фрагментов программыв зависимости от того, определено или нет в программе некоторое символическоеимя.ii Директива IFDEF проверяет, описано или нет в программе символическое имя,и если это так, то в объектный модуль помещается первый фрагмент программы (фрагмент_программы_1). В противном случае при наличии директивы ELSEв объектный код помещается второй фрагмент программы (фрагмент_программы_2). Если же директивы ELSE нет (и символическое имя в программе не описано), то вся часть программы между директивами IF и ENDIF игнорируетсяи в объектный модуль не включается.II Действие IFNDEF обратно действию IFDEF.
Если символического имени в программе нет, то транслируется первый фрагмент программы. Если оно присутствует, то при наличии ELSE транслируется второй фрагмент программы. ЕслиELSE отсутствует, а символическое имя в программе определено, то часть программы, заключенная между IFNDEF и ENDIF, игнорируется.В качестве примера рассмотрим ситуацию, когда в объектный модуль программы должен быть включен один из трех фрагментов кода в зависимости от значения некоторого идентификатора switch:'- если switch = 0, то сгенерировать фрагмент для вычисления выражения у=х- 2";'•• если switch = 1, то сгенерировать фрагмент для вычисления выражения у = х/2";.
если идентификатор switch не определен, то ничего не генерировать.Соответствующий фрагмент исходной программы может выглядеть так:ifndefEXITMelsesw;если sw не определено, то выйти из макроса;иначе - на вычислениеmov cl, пi f e swsal x, cl ;умножение на степень 2312Глава 14. Макросредства языка ассемблера;сдвигом влевоelsesar x ,cl.; деление на степень 2•.сдвигом вправоendifendifКак видим, эти директивы логически связаны с директивами IF и IFE, то есть ихможно применять в тех же самых случаях, что и последние. Есть еще одна интересная возможность использования этих директив. В главе б мы обсуждали форматкомандной строки TASM и говорили о ключах, которые можно в ней задавать.
Далееприведен один из них (см. приложение В, http://www.piter.com/download):/Ьимя_идентификатора[=значение]Использование этого ключа дает возможность управлять значением идентификатора прямо из командной строки, не меняя при этом текста программы. В качестве примера рассмотрим листинг 14.5. В этом коде мы пытаемся с помощьюмакроса контролировать процесс резервирования и инициализации некоторойобласти памяти в сегменте данных.Листинг 14.5.
Инициализация значения идентификатора из командной строки;prg_14_5.asmmasmmodelsmallstack256def_tab_50 macroifndef lenelselendisplay "sizejti не определено, задайте значение 10<size_m<50"exi tmlen GE 50GOTO exitendifif len LT 10:exitEXITMendifrept lendb 0endmendifendm;size_m=15.datadef_tab_50size_mif.codemain:mov ax,@datamov d s .