Глава 15. Использование условных директив
Существует два класса условных директив: директивы условного
ассемблирования и условные директивы генерации сообщений об ошиб-
ке. С помощью директив условного ассемблирования вы можете управ-
лять тем, какой код будет ассемблироваться в программе при опре-
деленных условиях.
Директивы условного ассемблирования позволяют вам генериро-
вать во время ассемблирования сообщения об ошибках при наступле-
нии определенных событий. Турбо Ассемблер выводит сообщение об
ошибке на экран и в файл листинга и предотвращает создание объек-
тного файла. В данной главе описывается, как можно использовать
имеющиеся условные директивы.
Синтаксис условных директив
Тремя директивами условного ассемблирования являются дирек-
тивы IFxxx, ELSEIFxxx и ERRxxx. Эти директивы используются также,
как операторы условия в языках высокого уровня.
Директива условного ассемблирования IFxxx
Вы можете использовать директиву условного ассемблирования
IFxxx для определения блока кода, который включается в объектный
файл при удовлетворении определенных условий (таких как определе-
ние идентификатора или установка какого-то значения). Приведем
синтаксис оператора условного ассемблирования:
IFxxx
тело_условия_true
EMDIF
или
IFxxx
тело_условия_true
ELSE
тело_условия_false
ENDIF
где IFxxx представляет следующие директивы:
IF
IF1
IF2
IFDEF
IFNDEF
IFB
IFNB
IFIDN
IFIDNI
IFDIF
IFDIFI
Каждая директива условного ассемблирования IFxxx задает
конкретное условие, при вычислении которого получается истинное
(true) или ложное (false) значение. Если условие имеет значение
true, то выполняется ассемблирование и помещение в объектный файл
блока ассемблируемого кода "тело_условия_true". Если при вычисле-
нии условия получается значение false, то Турбо Ассемблер пропус-
кает "тело_условия_true" и не включает его в объектный файл. При
наличие директивы ELSE, если условие имеет значение false, то ас-
семблируется и выводится в объектный файл блок "тело_усло-
вия_false". Если условие имеет значение true, то этот блок игно-
рируется. Условный блок завершается директивой ENDIF.
Кроме особых случаев директив IF1 и IF2 (которые мы обсудим
позднее) два описанных блока кода являются взаимноисключающими:
в объектный файл включается либо "тело_условия_true", либо "тело_
условия_false", но не оба блока одновременно. Кроме того, если вы
используете форму IFxxx.ELSE.ENDIF, один из блоков будет обя-
зательно включаться в объектный файл. Если используется форма
IFxxx.ENDIF, то "тело_условия_true" может включаться или не
включаться в объектный файл, в зависимости от условия.
При использовании вложенных директив IF и ELSE директива
ELSE всегда соответствует ближайшей директиве IF.
В следующем примере test является идентификатором, который
управляет включением кода (если идентификатор не определен, то
генерируется соответствующий блок кода) Идентификатор color уста-
навливается в ненулевое значение, если дисплей цветной, и равен
0, если дисплей монохромный.
От этих значений зависит фактическая генерация кода:
.
.
.
IFDEF test ; true, если test определен
; первая часть блока кода ; если test определен
IF color ; true, если color <> 0
; блок кода color ; если color <> 0
ELSE ;
; код для монохромного
; дисплея если color = 0
ENDIF ;
; вторая часть блока кода ; если test определен
ELSE ;
; другой код ; если test не определен
ENDIF
.
.
.
-------------T----------T-----------T--------------T------------¬
¦ test ¦определен ¦ определен ¦ не определен ¦не определен¦
¦ color ¦ 0 ¦ не 0 ¦ 0 ¦ не 0 ¦
+------------+----------+-----------+--------------+------------+
¦ код ¦ блок кода¦ блок кода ¦ другой код ¦другой код ¦
¦ ¦ 1 ¦ 1 ¦ ¦ ¦
¦ ¦ ¦ ¦ ¦ ¦
¦цветной/моно¦ блок кода¦ блок кода ¦ блок кода ¦ ¦
¦ ¦ color ¦ 2 ¦ 2 ¦ ¦
L------------+----------+-----------+--------------+-------------
Если идентификатор test не определен,то не ассемблируется ни
код для цветного дисплея (color), ни для монохромного, поскольку
все это включено в блок условного ассемблирования, который ас-
семблируется только при определенном идентификаторе test.
Директивы условного ассемблирования ELSEIFxxx
Вы можете использовать директивы условного ассемблирования
ELSEIFxxx как сокращенную форму, когда требуется использовать
несколько директив IF. Директива ELSEIFxxx представляет собой эк-
вивалент директивы ELSE, за которой следует вложенная директива
IFxxx, но дает более компактный код. Например:
.
.
.
IF mode EQ 0
; кода для mode = 0
ELSEIF mode LT 5
; код для coe = 14
ELSE
; код для mode = 5.
ENDIF
.
.
.
сравните его со следующим:
.
.
.
IF mode EQ 0
; кода для mode = 0
ELSE
IF mode LT 5
; код для coe = 14
ELSE
; код для mode = 5.
ENDIF
ENDIF
.
.
.
Вне оператора IFxxx директиву ELSEIFxxx использовать нельзя.
Директивы генерации сообщений об ошибке ERRxx
Директива ERRxxx генерирует при удовлетворении определенных
условий сообщения пользователя об ошибке. Она имеет следующий об-
щий синтаксис:
ERRxxx [аргументы] [сообщение]
В этом случае директива ERRxxx представляет какую-либо из
директив условной генерации сообщения об ошибке (такие как
ERRIFB, .ERRB и т.д.).
"Аргументы" представляют аргументы, которые могут потребо-
ваться в директиве для вычисления условия. Некоторые директивы
требуют выражения, другие требуют символьного выражения, а неко-
торые - одно или два текстовых выражений. Некоторые из директив
вовсе не требуют аргументов.
Если указано "сообщение", то оно задает необязательное сооб-
щение, которое выводится с ошибкой. Сообщение должно быть заклю-
чено в кавычки (' или ").
Директивы генерации сообщений об ошибке генерируют пользова-
тельское сообщение об ошибке, которое выводится на экран и
включается в файл листинга (если он имеется) в месте расположения
директивы в исходном коде. Если директива задает сообщение, оно
выводится на той же строке непосредственно за ошибкой. Например,
директива:
ERRIFNDEF foo "foo не определено!"
если идентификатор foo не определен при обнаружении ошибки, при-
ведет к генерации ошибки:
User error: "foo не определено!"
Описания конкретных директив
Далее следует описание директив.
Безусловные директивы генерации сообщений об ошибке
Безусловными директивами генерации сообщений об ошибке явля-
ются директивы ERR и .ERR. Эти директивы всегда генерируют ошибку
и не требуют аргументов, хотя могут содержать необязательное со-
общение. Директиву .ERR можно использовать только в режиме MASM.
Условные директивы с выражениями
Эти директивы обеспечивают условное ассемблирование или ге-
нерацию сообщений об ошибке на основе результатов вычисления в
Турбо Ассемблере выражения. Во всех этих директивах при вычисле-
нии выражения должна получаться константа, и оно не может содер-
жать опережающих ссылок. Если при вычислении выражения получается
0, Турбо Ассемблер рассматривает выражение, как ложное (false). в
противном случае оно рассматривается как истинное (true).
В следующей таблице показаны директивы условного ассемблиро-
вания, использующие выражения.
Директивы условного ассемблирования, использующие сообщения
Таблица 15.1
----------------------T-----------------------------------------¬
¦ Директива IFxxx ¦ Ассемблирует "тело_условия_true" если: ¦
+---------------------+-----------------------------------------+
¦ IF выражение ¦ при вычислении выражения получается ¦
¦ ¦ значение true. ¦
¦ ¦ ¦
¦ IFE выражение ¦ при вычислении выражения получается ¦
¦ ¦ значение false. ¦
¦ ¦ ¦
¦ ELSEIF выражение ¦ при вычислении выражения получается ¦
¦ ¦ значение true. ¦
¦ ¦ ¦
¦ ELSEIFE выражение ¦ при вычислении выражения получается ¦
¦ ¦ значение false. ¦
L---------------------+------------------------------------------
В следующей таблице показаны директивы генерации сообщений
об ошибке, в которых используются выражения:
Директивы генерации сообщений об ошибке, использующие выражения
Таблица. 15.2
---------------------T------------------------------------------¬
¦ Директива ERRxxx ¦ Генерируется сообщение user error, если: ¦
+--------------------+------------------------------------------+
¦ ERRIF выражение ¦ при вычислении выражения получается зна- ¦
¦ ¦ чение true. ¦
¦ ¦ ¦
¦ .ERRNZ выражение ¦ при вычислении выражения получается зна- ¦
¦ ¦ чение true (только в режиме MASM). ¦
¦ ¦ ¦
¦ ERRIFE выражение ¦ при вычислении выражения получается зна- ¦
¦ ¦ чение false. ¦
¦ ¦ ¦
¦ .ERRE выражение ¦ при вычислении выражения получается зна- ¦
¦ ¦ чение false (только в режиме MASM). ¦
L--------------------+-------------------------------------------
Условные директивы с идентификатором
Эти директивы обеспечивают условное ассемблирование или ге-
нерацию сообщения об ошибке на основе того, является ли опреде-
ленным один или более идентификаторов. Данные идентификаторы объ-
единены в выражение с идентификаторами.
Выражение с идентификаторами - это выражение, состоящее из
имен идентификаторов, булевских операций AND, OR, NOT и круглых
скобок. В выражении с идентификаторами каждое имя идентификатора
интерпретируется как булевское значение, при вычислении которого
получается значение true, если идентификатор существует (опреде-
лен), или false, если идентификатор не существует (даже если он
определяется в модуле позднее). Турбо Ассемблер комбинирует эти
значения, используя булевские операции, для получения конечного
значения true или false. В своей простейшей форме выражение с
идентификаторами содержит имя единственного идентификатора и дает
при вычислении значение true, если этот идентификатор определен.
Синтаксические правила в выражении с идентификаторами аналогичны
тем, которые используются в выражениях Турбо Ассемблера. Напри-
мер, если идентификатор foo определен, а идентификатор bar - нет,
то при вычислении выражения с идентификаторами получаются следую-
щие результаты:
Вычисление определенных и неопределенных идентификаторов
Таблица 15.3
------------------------------------T---------------------------¬
¦ Выражение с идентификаторами ¦ Результат ¦
+-----------------------------------+---------------------------+
¦ foo ¦ True ¦
¦ ¦ ¦
¦ bar ¦ False ¦
¦ ¦ ¦
¦ not foo ¦ False ¦
¦ ¦ ¦
¦ not bar ¦ True ¦
¦ ¦ ¦
¦ foo OR bar ¦ True ¦
¦ ¦ ¦
¦ foo AND bar ¦ False ¦
¦ ¦ ¦
¦ NOT (foo AND bar) ¦ True ¦
¦ ¦ ¦
¦ NOT foo OR NOT bar ¦ True (то же, что ¦
¦ ¦ (NOT foo) OR (NOT bar) ¦
L-----------------------------------+----------------------------
В следующей таблице показаны директивы, которые управляют
ассемблированием и используют выражение с идентификаторами:
Директивы, использующие выражение с идентификаторами Таблица 15.4
-------------------------T--------------------------------------¬
¦Директива IFxxx ¦ Ассемблирует "тело_условия_true" если¦
+------------------------+--------------------------------------+
¦IFDEF выражение_ид ¦ при вычислении выражения получается¦
¦ ¦ значение true. ¦
¦ ¦ ¦
¦IFNDEF выражение_ид ¦ при вычислении выражения получается¦
¦ ¦ значение false. ¦
¦ ¦ ¦
¦ELSEIFDEF выражение_ид ¦ при вычислении выражения получается¦
¦ ¦ значение true. ¦
¦ ¦ ¦
¦ELSEIFNDEF выражение_ид ¦ при вычислении выражения получается¦
¦ ¦ значение false. ¦
L------------------------+---------------------------------------
В следующей таблице показаны директивы выводы сообщения об
ошибке, которые используют выражение с идентификаторами:
Директивы генерации сообщения об ошибке Таблица 15.5
-------------------------T--------------------------------------¬
¦Директива IFxxx ¦ Ассемблирует "тело_условия_true" если¦
+------------------------+--------------------------------------+
¦ERRIFDEF выражение_ид ¦ при вычислении выражения получается¦
¦ ¦ значение true. ¦
¦ ¦ ¦
¦.ERRDEF выражение_ид ¦ при вычислении выражения получается¦
¦ ¦ значение true (только для режима¦
¦ ¦ MASM). ¦
¦ ¦ ¦
¦ERRIFNDEF выражение_ид ¦ при вычислении выражения получается¦
¦ ¦ значение false. ¦
¦ ¦ ¦
¦.ERRNDEF выражение_ид ¦ при вычислении выражения получается¦
¦ ¦ значение false (только в режиме¦
¦ ¦ MASM). ¦
L------------------------+---------------------------------------
Например, следующие условия генерации сообщения об ошибке
эквивалентны и приводят к генерации ошибки в случае определения
foo и bar:
ERRIFDEF foo AND bar
ERRIFNDEF NOT ( foo AND bar )
ERRIFBDEF NOT foo OR NOT bar
Условные директивы с текстовыми строками
Эти директивы условное ассемблирование или генерацию сообще-
ний об ошибке на основе содержимого текстовой строки. Текстовой
строкой может быть либо строка, заключенная в угловые скобки
(<>), либо имя текстовой макрокоманды с предшествующим символом
%. Например:
<ABC> ; текстовая строка ABC
%foo ; содержимое текстовой макрокоманды foo
Примечание: Об определении текстовых макрокоманд и ра-
боте с ними рассказывается в Главе 14.
Директивы условного ассемблирования, использующие текстовую
строку, показаны в следующей таблице:
Директивы условного
ассемблирования, использующие текстовую строку Таблица 15.6
-----------------------T----------------------------------------¬
¦ Директива IFxxx ¦ ассемблирует "тело_условия_true", если:¦
+----------------------+----------------------------------------+
¦ IFNB текст_строка ¦ "текст_строка" не состоит из одних про-¦
¦ ¦ белов. ¦
¦ ¦ ¦
¦ IFB текст_строка ¦ "текст_строка" не пуста. ¦
¦ ¦ ¦
¦ IFIDN текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ идентичны. ¦
¦ ¦ ¦
¦ IFINDI текст_строка_1¦ "текст_строка_1" и "текст_строка_2" ¦
¦ ,текст_строка_2 ¦ идентичны (регистр символов не учиты- ¦
¦ ¦ вается. ¦
¦ ¦ ¦
¦ IFDIF текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ различны. ¦
¦ ¦ ¦
¦ IFDEFI текст_строка_1¦ "текст_строка_1" и "текст_строка_2" ¦
¦ ,текст_строка_2 ¦ различны (регистр символов игнорирует- ¦
¦ ¦ ся. ¦
¦ ¦ ¦
¦ ELSEIFNB текст_строка¦ "текст_строка" не состоит из пробелов. ¦
¦ ¦ ¦
¦ ELSEIFB текст_строка ¦ "текст_строка" не пуста. ¦
¦ ¦ ¦
¦ ELSEIFIDN текст_стро-¦ "текст_строка_1" и "текст_строка_2" ¦
¦ ка_1, текст_строка_2¦ идентичны. ¦
¦ ¦ ¦
¦ ¦ ¦
¦ ELSEIDNI текст_стро- ¦ "текст_строка_1" и "текст_строка_2" ¦
¦ ка_1,текст_строка_2 ¦ идентичны (регистр символов игнориру- ¦
¦ ¦ ется). ¦
¦ ¦ ¦
¦ ELSEIFDIF текст_стро-¦ "текст_строка_1" и "текст_строка_2" ¦
¦ ка_1,текст_строка_2 ¦ различны. ¦
¦ ¦ ¦
¦ ELSEIFDIFI текст_стро¦ "текст_строка_1" и "текст_строка_2" ¦
¦ -ка_1,текст_строка_2¦ различны (регистр символов игнориру- ¦
¦ ¦ ется). ¦
L----------------------+-----------------------------------------
Использующие текстовую строку директивы генерации сообщения
об ошибке показаны в следующей таблице:
Директивы вывода сообщений
об ошибке использующие текстовую строку Таблица 15.6
-------------------------T--------------------------------------¬
¦Директива ERRxxx ¦ Генерирует сообщение об ошибке, если:¦
+------------------------+--------------------------------------+
¦ERRIFNB текст_строка ¦ "текст_строка" не состоит из одних¦
¦ ¦ пробелов. ¦
¦ ¦ ¦
¦.ERRIFNB текст_строка ¦ "текст_строка" не состоит из одних¦
¦ ¦ пробелов (только для режима MASM). ¦
¦ ¦ ¦
¦ERRIFB текст_строка ¦ "текст_строка" состоит из пробелов. ¦
¦ ¦ ¦
¦.ERRB текст_строка ¦ "текст_строка" состоит из одних про-¦
¦ ¦ белов. ¦
¦ ¦ ¦
¦ERRIFIDN текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ идентичны. ¦
¦ ¦ ¦
¦.ERRIDN текст_строка_1, ¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ идентичны (только для режима MASM). ¦
¦ ¦ ¦
¦ERRIFIDNI текст_строка_1¦ "текст_строка_1" и "текст_строка_2" ¦
¦ ,текст_строка_2 ¦ идентичны (регистр символов игнориру-¦
¦ ¦ ется). ¦
¦ ¦ ¦
¦.ERRIDNI текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ идентичны (регистр символов игнориру-¦
¦ ¦ ется) - только для режима MASM. ¦
¦ ¦ ¦
¦ERRIFDIF текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ различны. ¦
¦ ¦ ¦
¦.ERRDIF текст_строка_1, ¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ различны (только для режима MASM). ¦
¦ ¦ ¦
¦ERIFDIFI текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ различны (регистр символов игнориру- ¦
¦ ¦ ется). ¦
¦ ¦ ¦
¦.ERRFIFI текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦
¦ текст_строка_2 ¦ различны (регистр символов игнориру- ¦
¦ ¦ ется) - только для режима MASM. ¦
L------------------------+---------------------------------------
Используйте эти директивы для проверки передаваемых макроко-
мандам аргументов (однако их можно использовать не только в мак-
рокомандах).
При использовании их в макроопределениях директивы IFB и
IFNB позволяют определить, передали ли вы в макрокоманду нужное
число аргументов. Если при вызове макрокоманды вы передали слиш-
ком мало аргументов, Турбо Ассемблер не генерирует сообщение об
ошибке. Незаданные аргументы просто остаются пустыми. Таким обра-
зом, вы можете определить макрокоманду, воспринимающую переменное
число аргументов. Например:
.
.
.
load MACRO addr, reg
IFNB <reg>
MOV reg,addr
ELSE
MOV ax,addr
ENDIF
ENDM
.
.
.
Вы можете вызывать макрокоманду данного примера, как load
test,cx, что даст генерацию инструкции mov cx,test, или вызвать
ее как load test, то приведет к генерации инструкции mov ax,test,
поскольку второй параметр пуст. Можно также использовать директи-
ву ERRIFB для генерации сообщения об ошибке, если в вызове макро-
команды пропущен аргумент:
.
.
.
load MACRO addr
ERRIFNB <addr>
MOV reg,addr
ENDM
.
.
.
Если эту макрокоманду вызвать с помощью load, а не с помощью
load test, то будет генерироваться ошибка.
Условия выполнения прохода Ассемблером
Следующие директивы обеспечивают выполнение условного ас-
семблирования или генерацию ошибки на основе текущего прохода Ас-
семблера:
----------------------T-----------------------------------------¬
¦ Директива IFxxx ¦ ассемблирует "тело_условия_true", если:¦
+---------------------+-----------------------------------------+
¦ IF1 ¦ Турбо Ассемблер выполняет первый проход.¦
¦ IF2 ¦ Турбо Ассемблер выполняет второй проход.¦
L---------------------+------------------------------------------
----------------------T-----------------------------------------¬
¦ Директива ERRxxx ¦ генерирует ошибку user error, если: ¦
+---------------------+-----------------------------------------+
¦ ERRIF1 ¦ Турбо Ассемблер выполняет первый проход.¦
¦ ¦ ¦
¦ .ERR1 ¦ Турбо Ассемблер выполняет первый проход¦
¦ ¦ (только для режима MASM). ¦
¦ ¦ ¦
¦ ERRIF2 ¦ Турбо Ассемблер выполняет второй проход.¦
¦ ¦ ¦
¦ .ERR2 ¦ Турбо Ассемблер выполняет второй проход¦
¦ ¦ (только для режима MASM). ¦
L---------------------+------------------------------------------
Обычно Турбо Ассемблер работает как однопроходный ассемблер.
Если вы используете средство многопроходной работы Турбо Ассемб-
лера (вызывая его с параметром командной строки /m), то при не-
обходимости используется несколько проходов.
Поскольку Турбо Ассемблер всегда выполняет по крайней мере
один проход, директива условного ассемблирования IF1 всегда будет
ассемблировать код своего условного блока, а директивы .ERR1 и
ERRIF1 всегда будут генерировать сообщение об ошибке (но только
на первом проходе).
Если вы используете любую из этих директив и не разрешаете
многопроходную работу, то Турбо Ассемблер будет генерировать для
всех таких директив предупреждение "Pass dependent construction"
("Конструкция, зависящая от прохода"), чтобы предупредить вас о
возможно опасном пропуске кода. Если вы разрешите многопроходную
работу, Турбо Ассемблер будет выполнять точно два прохода и гене-
рировать предупреждение Vaximum compatibility pass was done (Вы-
полнен проход с целью обеспечения максимальной совместимости).
Включение условных директив в файл листинга
Обычно код условного ассемблирования с ложным условием
(false) в листинг не включается. Используя директивы Турбо Ас-
семблера и параметры командной строки, вы можете это переопреде-
лить.
Примечание: Более подробная информация содержится в
Главе 2 и Главе 17.
Назад | Содержание | Вперед