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 — это метка, и её тип — численное выражение.
Пример расширенной инструкции mov, которая позволяет перемещать данные между ячейками памяти:
macro mov dest,src
{
if dest src eqtype [0] [0]
push src
pop dest
else
mov dest,src
end if
}
mov [var1], 5
mov [var1], [var2]
преобразуется препроцессором в:
if [var1] 5 eqtype [0] [0] ;не верно
push 5
pop [var1]
else
mov [var1],5
end if
if [var1] [var2] eqtype [0] [0] ;верно
push [var2]
pop [var1]
else
mov [var1], [var2]
end if
и будет ассемблировано в:
mov [var1], 5
push [var2]
pop [var1]
Хотя более удобно для восприятия реализовать макрос используя логический оператор И — &:
macro mov dest,src
{
if (dest eqtype [0]) & (src eqtype [0])
push src
pop dest
else
mov dest, src
end if
}
Пример с использованием EQTYPE с четырьмя аргументами приведён для демонстрации возможностей, обычно проще использовать в таких случаях &. Кстати, в качестве аргументов, возможно использовать некорректные выражения — достаточно, чтобы лексический анализатор распознал их тип. Но это не является документированным, так что не будем этот обсуждать.