Руководство по препроцессору FASM - страница 6

стр.

, >| и т. п.) — RTFM. Я лишь расскажу об операторах проверки условия используемых препроцессором.

7.1. Оператор EQ

Простейший логический оператор — это >EQ. Он всего лишь сравнивает два идентификатора — одинаковы ли их значение. Значение >abcd eq abcd — истина, а >abcd eq 1 — ложь и так далее… Это полезно для сравнения символов, которые будут обработаны препроцессором:

>STRINGS equ ASCII

>if STRINGS eq ASCII

> db 'Oh yeah',0

>else if STRINGS eq UNICODE

> du 'Oh yeah',0

>else

> display 'unknown string type'

>end if

после обработки препроцессором, это примет вид:

>if ASCII eq ASCII

> db 'Oh yeah',0

>else if ASCII eq UNICODE

> du 'Oh yeah',0

>else

> display 'unknown string type'

>end if

Здесь только первое условие (>ASCII eq ASCII) выполняется, так что будет ассемблировано только >db 'Oh yeah',0

Другой вариант:

>STRINGS equ UNICODE  ;разница здесь, UNICODE вместо ASCII

>if STRINGS eq ASCII

> db 'Oh yeah',0

>else if STRINGS eq UNICODE

> du 'Oh yeah',0

>else

> display 'unknown string type'

>end if

получим:

>if UNICODE eq ASCII

> db 'Oh yeah',0

>else if UNICODE eq UNICODE

> du 'Oh yeah',0

>else

> display 'unknown string type'

>end if

Тут уже первое условие (>UNICODE eq ASCII) будет ложно, второе (>UNICODE eq UNICODE) — верно, будет ассемблироваться >du 'Oh yeah',0.

Несколько лучшее применение этого — проверка аргументов макросов, вроде:

>macro item type,value

>{

> if type eq BYTE

>  db value

> else if type eq WORD

>  dw value

> else if type eq DWORD

>  dd value

> else if type eq STRING

>  db value,0

> end if

>}

>item BYTE,1

>item STRING,'aaaaaa'

будет:

>if BYTE eq BYTE

> db 1

>else if BYTE eq WORD

> dw 1

>else if BYTE eq DWORD

> dd 1

>else if BYTE eq STRING

> db 1,0

>end if

>if STRING eq BYTE

> db 'aaaaaa'

>else if STRING eq WORD

> dw 'aaaaaa'

>else if STRING eq DWORD

> dd 'aaaaaa'

>else if STRING eq STRING

> db 'aaaaaa',0

>end if

ассемблироваться будут только 2 команды:

>db 1

>db 'aaaaaa',0

Подобно всем другим операторам препроцессора, >EQ может работать с пустыми аргументами. Это значит, что, например, >if eq верно, а >if 5 eq — ложно и т. п.

Пример макроса:

>macro mov dest,src,src2

>{

> if src2 eq

>  mov dest, src

> else

>  mov dest, src

>  mov src, src2

> end if

>}

здесь, если есть третий аргумент, то будут ассемблироваться 2 последних команды, если нет — то только одна первая.

7.2. Оператор EQTYPE

Ещё один оператор — >EQTYPE. Он определяет, одинаков ли тип идентификаторов.

Существующие типы:

отдельные строки символов, заключённые в кавычки (те, которые не являются частью численных выражений)

вещественные числа (с плавающей точкой)

любые численные выражения, например, >2+2 (любой неизвестный символ будет рассматриваться как метка, так что он будет считаться подобным выражением)

адреса — численные выражения в квадратных скобках (учитывая оператор размерности и префикс сегмента)

мнемоники инструкций

регистры

операторы размерности

операторы >NEAR и >FAR

операторы >USE16 и >USE32

пустые аргументы (пробелы, символы табуляции)

Пример макроса, который позволяет использовать переменную в памяти в качестве счётчика в инструкции >SHL (например >shl ax, [myvar]):

>macro shl dest, count

>{

> if count eqtype [0]  ;если count — ячейка памяти

>  push cx

>  mov cl, count

>  shl dest, cl

>  pop cx

> else             ;если count другого типа

>  shl dest, count ;просто используем обычную shl

> end if

>}

>shl ax, 5

>byte_variable db 5

>shl ax, [byte_variable]

получится:

>if 5 eqtype [0]

> push cx

> mov cl, 5

> shl ax, cl

> pop cx

>else

> shl ax, 5

>end if

>byte_variable db 5

>if [byte_variable] eqtype [0]

> push cx

> mov cl, [byte_variable]

> shl ax, cl

> pop cx

>else

> shl ax, [byte_variable]

>end if

в результате обработки условий конечный результат будет:

> shl ax, 5

>byte_variable db 5

> push cx

> mov cl, [byte variable]

> shl ax, cl

> pop cx

Заметьте, что >shl ax, byte [myvar] не будет работать с этим макросом, так как условие >byte [variable] eqtype [0] не выполняется. Читаем дальше.

Когда мы сравниваем что-то посредством >EQTYPE, то это что-то может быть не только единичным идентификатором, но и их комбинацией. В таком случае, результат >eqtype истина, если не только типы, но и порядок идентификаторов совпадают. К примеру, >if eax 4 eqtype ebx name — верно, так как >name — это метка, и её тип — численное выражение.