Справочник по языку Ассемблера IBM PC

     

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


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

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

Данные директивы позволяют управлять трансляцией фрагментов программы в зависимости от того, определено или нет в программе некоторое символическое_имя. Директива 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 не определено, то выйти из макроса EXITM else ;иначе — на вычисление mov cl,n ife sw sal x,cl ;умножение на степень 2 сдвигом влево else sar x,cl ;деление на степень 2 сдвигом вправо endif endif



Как видим, эти директивы логически связаны с директивами IF

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

Листинг 6. Инициализация значения идентификатора из командной строки ;prg_13_5.asm masm model small stack 256 def_tab_50 macro len ifndef len display 'size_m не определено, задайте значение 10exitm else if len GE 50 GOTO exit endif if len LT 10 :exit EXITM endif rept len db 0 endm endif endm ;size_m=15 .data def_tab_50 size_m

.code main: mov ax,@data mov ds,ax exit: mov ax,4c00h int 21h end main

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

  1. Определите где-то в начале исходного текста программы значение этой переменной с помощью equ:

    size_m equ 15

  2. Запустите программу на трансляцию командной строкой вида
    tasm /dsize_m=15 /zi prg_13_2,,,
  3. В листинге 6 мы использовали еще одну возможность транслятора — директиву , с помощью которой можно формировать пользовательское сообщение в процессе трансляции программы.



    Содержание раздела