Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Директивы условной компиляции



Последний тип макросредств — директивы условной компиляции.

Существует два типа этих директив:

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

С этими директивами применяются директивы управления процессом генерации макрорасширений EXITM и GOTO.

Директива EXITM не имеет операндов, и ее действие заключается в том, что она немедленно прекращает процесс генерации макрорасширения, начиная с того места, где она встретилась в макроопределении.

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

: имя_метки

Примеры применения этих директив будут приведены ниже.

Директивы компиляции по условию

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

Введение в язык ассемблера этих директив значительно повышает его мощь.

Всего имеется 10 типов условных директив компиляции. Их логично попарно объединить в четыре группы:

  1. Директивы IF и IFE — условная трансляция по результату вычисления логического выражения.
  2. Директивы IFDEF и IFNDEF — условная трансляция по факту определения символического имени.
  3. Директивы IFB и IFNB — условная трансляция по факту определения фактического аргумента при вызове макрокоманды.
  4. Директивы IFIDN , IFIDNI , IFDIF и IFDIFI — условная трансляция по результату сравнения строк символов.

Условные директивы компиляции имеют общий синтаксис и применяются в составе следующей синтаксической конструкции:

IFxxx логическое_выражение_или_аргументыфрагмент_программы_1 ELSEфрагмент_программы_2ENDIF

Заключение некоторых фрагментов текста программы — фрагмент_программы_1 и фрагмент_программы_2 — между директивами IFxxx, ELSE и ENDIF приводит к их выборочному включению в объектный модуль. Какой именно из этих фрагментов — фрагмент_программы_1 или фрагмент_программы_2 — будет включен в объектный модуль, зависит от конкретного типа условной директивы, задаваемого значением xxx, и значения условия, определяемого операндом (операндами) условной директивы логическое_выражение_или_аргумент(ы) .

Синтаксические конструкции, соответствующие директивам условной компиляции, могут быть вложенными друг в друга (см. " Вложенность директив условной трансляции" )

Директивы IF и IFE

Синтаксис этих директив следующий:

IF(E) логическое_выражениефрагмент_программы_1 ELSEфрагмент_программы_2ENDIF

Обработка этих директив макроассемблером заключается в вычислении логического_выражения и включении в объектный модуль фрагмент_программы_1 или фрагмент_программы_2 в зависимости от того, в какой директиве IF или IFE это выражение встретилось:

  • если в директиве IF логическое выражение истинно, то в объектный модуль помещается фрагмент_программы_1 .
  • Если логическое выражение ложно, то при наличии директивы ELSE в объектный код помещается фрагмент_программы_2 . Если же директивы ELSE нет, то вся часть программы между директивами IF и ENDIF игнорируется и в объектный модуль ничего не включается. Кстати сказать, понятие истинности и ложности значения логического_выражения весьма условно. Ложным оно будет считаться, если его значение равно нулю, а истинным — при любом значении, отличном от нуля.
  • директива IFE аналогично директиве IF анализирует значение логического_выражения . Но теперь для включения фрагмент_программы_1 в объектный модуль требуется, чтобы логическое_выражение имело значение “ложь”.

Директивы IF и IFE очень удобно использовать при необходимости изменения текста программы в зависимости от некоторых условий.

К примеру, составим макрос для определения в программе области памяти длиной не более 50 и не менее 10 байт (листинг 5).

Листинг 5. Использование условных директив IF и IFE< 1>; prg_13_4.asm< 2> masm< 3> model small< 4> stack 256< 5> def_tab_50 macro len< 6> if len GE 50< 7> GOTO exit< 8> endif< 9> if len LT 10< 10>: exit< 11> EXITM< 12> endif< 13> rept len< 14> db 0< 15> endm< 16> endm< 17>.data< 18> def_tab_50 15< 19> def_tab_50 5< 20>.code< 21> main: < 22> mov ax, @data< 23> mov ds, ax< 24> exit: < 25> mov ax, 4c00h< 26> int 21h< 27> end mainENDIF

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

В нем вы увидите, что в результате трансляции строка 18 листинга 5 развернется в пятнадцать нулевых байт, а строка 19 оставит макрогенератор совершенно равнодушным, так как значение фактического операнда в строках 6 и 9 будет ложным. Обратите внимание, что для обработки реакции на ложный результат анализа в условной директиве мы использовали макродирективы EXITM и GOTO.

Другой интересный и полезный вариант применения директив IF и IFE отладочная печать.

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

Можно определить в программе некоторую переменную, к примеру debug, и использовать ее совместно с условными директивами IF или IFE. К примеру,

< 1>...< 2> debug equ 1< 3>...< 4>.code< 5>...< 6> if debug< 7>; любые команды и директивы ассемблера< 8>; (вывод на печать или монитор)< 9> endif

На время отладки и тестирования программы вы можете заключить отдельные участки кода в своеобразные операторные скобки в виде директив IF и ENDIF (строки 6-9 последнего фрагмента), которые реагируют на значение логической переменной debug. При значении debug = 0 транслятор полностью проигнорирует текст внутри этих условных операторных скобок; при debug = 1, наоборот, будут выполнены все действия, описанные внутри них.

Директивы IFDEF и IFNDEF

Синтаксис этих директив следующий:

IF(N)DEF символическое_имяфрагмент_программы_1 ELSEфрагмент_программы_2ENDIF

Данные директивы позволяют управлять трансляцией фрагментов программы в зависимости от того, определено или нет в программе некоторое символическое_имя . Директива IFDEF проверяет, описано или нет в программе символическое_имя , и если это так, то в объектный модуль помещается фрагмент_программы_1 . В противном случае, при наличии директивы ELSE, в объектный код помещается фрагмент_программы_2 .

Если же директивы ELSE нет (и символическое_имя в программе не описано), то вся часть программы между директивами IF и ENDIF игнорируется и в объектный модуль не включается.

Действие IFNDEF обратно IFDEF. Если символического_имени в программе нет, то транслируется фрагмент_программы_1 . Если оно присутствует, то при наличии ELSE транслируется фрагмент_программы_2 . Если ELSE отсутствует, а символическое_имя в программе определено, то часть программы, заключенная между IFNDEF и ENDIF, игнорируется.

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

  • если switch = 0, то сгенерировать фрагмент для вычисления выражения
  • y = x*2**n;
  • если switch = 1, то сгенерировать фрагмент для вычисления выражения
  • y = x/2**n;
  • если switch не определен, то ничего не генерировать.

Соответствующий фрагмент исходной программы может выглядеть так:

ifndef sw; если sw не определено, то выйти из макросаEXITMelse; иначе — на вычисление mov cl, nife sw sal x, cl; умножение на степень 2 сдвигом влево else sar x, cl; деление на степень 2 сдвигом вправо endifendif

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

Есть еще одна интересная возможность использования этих директив. На уроке 4 мы обсуждали формат командной строки и говорили об опциях, которые в ней можно задавать. Вспомните одну из опций командной строки TASM — опцию

/dидентификатор=значение.

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

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

Листинг 6. Инициализация значения идентификатора из командной строки< 1>; prg_13_5.asm< 2> masm< 3> model small< 4> stack 256< 5> def_tab_50 macro len< 6> ifndef len< 7> display 'size_m не определено, задайте значение 10< SIZE_Mexitm< 9> else< 10> if len GE 50< 11> GOTO exit< 12> endif< 13> if len LT 10< 14>: exit< 15> EXITM< 16> endif< 17> rept len< 18> db 0< 19> endm< 20> endif< 21> endm< 22>; size_m=15< 23>.data< 24> def_tab_50 size_m< 25> < 26>.code< 27> main: < 28> mov ax, @data< 29> mov ds, ax< 30> exit: < 31> mov ax, 4c00h< 32> int 21h< 33> end main

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

  1. Определите где-то в начале исходного текста программы значение этой переменной с помощью equ:
size_m equ 15
  1. Запустите программу на трансляцию командной строкой вида
  2. tasm /dsize_m=15 /zi prg_13_2,,,

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

Директивы IFB и IFNB

Синтаксис этих директив следующий:

IF(N)B аргументфрагмент_программы_1 ELSEфрагмент_программы_2ENDIF

Данные директивы используются для проверки фактических параметров, передаваемых в макрос. При вызове макрокоманды они анализируют значение аргумента, и в зависимости от того, равно оно пробелу или нет, транслируется либо фрагмент_программы_1 , либо фрагмент_программы_1 . Какой именно фрагмент будет выбран, зависит от кода директивы:

  • Директива IFB проверяет равенство аргумента пробелу. В качестве аргумента могут выступать имя или число.
  • Если его значение равно пробелу (то есть фактический аргумент при вызове макрокоманды не был задан), то транслируется и помещается в объектный модуль фрагмент_программы_1 .
  • В противном случае, при наличии директивы ELSE, в объектный код помещается фрагмент_программы_1 . Если же директивы ELSE нет, то при равенстве аргумента пробелу вся часть программы между директивами IFB и ENDIF игнорируется и в объектный модуль не включается.
  • Действие IFNB обратно IFB. Если значение аргумента в программе не равно пробелу, то транслируется фрагмент_программы_1 .
  • В противном случае, при наличии директивы ELSE, в объектный код помещается фрагмент_программы_1 . Если же директивы ELSE нет, то вся часть программы (при неравенстве аргумента пробелу) между директивами IFNB и ENDIF игнорируется и в объектный модуль не включается.

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

show macro regifb display 'не задан регистр'exitmendif...endm

Если теперь в сегменте кода вызвать макрос show без аргументов, то будет выведено сообщение о том, что не задан регистр и генерация макрорасширения будет прекращена директивой exitm.


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-05-28; Просмотров: 1123; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.018 с.)
Главная | Случайная страница | Обратная связь