rept 3 counter
{
byte#counter db counter
}
Сгенерирует строки:
byte1 db 1
byte2 db 2
byte3 db 3
Механизм повторения, применяемый к блокам «rept
» такой же, как тот, что используется для обработки множественных групп аргументов макросов, то есть директивы, такие как «forward
», «common
» и «reverse
» могут использоваться их обычном значении.
Итак, такой макрос:
rept 7 num { reverse display `num }
покажет символы от 7 до 1 как текст. Директива «local
» работает так же, как внутри макросов с несколькими группами аргументов, то есть:
rept 21
{
local label
labeclass="underline" loop label
}
сгенерирует уникальную метку для каждого дубликата. Символ-счетчик обычно начинает с 1, но вы можете объявить другое базовое значение, предваренное запятой, сразу же после имени счетчика. Например:
rept 8 n:0 { pxor xmm#n,xmm#n }
Сгенерирует код, очищающий содержимое регистров SSE. Вы можете определить несколько счетчиков, разделенных запятыми, и каждый может иметь свою базу.
«irp
» итерирует один аргумент через данный список параметров. Синтаксис такой: за «irp
» следует имя аргумента, далее запятая и далее список параметров. Параметры определяются таким же образом, как в вызове стандартного макроса, то есть они должны разделяться запятыми и каждый может быть заключен между знаками «<» и «>». Так же за именем аргумента может следовать «*
» для обозначения того, что он не может иметь пустое значение. Такой блок:
irp value, 2,3,5
{ db value }
сгенерирует строки:
db 2
db 3
db 5
«irps
» итерирует через данный список символов, за директивой должно следовать имя аргумента, далее запятая и далее последовательность любых символов. Каждый символ в последовательности, независимо от того, символы ли это имен, знаки символов или строки в кавычках, становится значением аргумента на одну итерацию. Если за запятой никаких символов не следует, то итераций не производится вообще. Этот пример:
irps reg, al bx ecx
{ xor reg,reg }
сгенерирует строки:
xor al,al
xor bx,bx
xor ecx,ecx
Блоки, определенные директивами «irp
» и «irps
», обрабатываются так же, как макросы, то есть операнды и директивы, специфичные для макросов могут в них свободно использоваться.
2.3.6 Условный препроцессинг
При применении директивы «match
» некоторый блок кода обрабатывается препроцессором и передаётся ассемблеру, только если заданная последовательность символов совпадает с образцом. Образец идет первым, заканчивается запятой, далее идут символы, которые должны подходить под образец, и далее блок кода, заключенный в фигурные скобки, как макроинструкция.
Есть несколько правил для построения выражения для сравнения, первое — это любые символьные знаки и строки в кавычках должны соответствовать абсолютно точно. В этом примере:
match +,+ { include 'first.inc' }
match +,- { include 'second.inc' }
Первый файл будет включен, так как «+
» после запятой соответствует «+
» в образце, а второй файл не будет включен, так как совпадения нет.
Чтобы соответствовать любому другому символу буквально, он должен предварятья знаком «=
» в образце. Также чтобы привести в соответствие сам знак «=
», или запятую должны использоваться конструкции «==
» и «=,
». Например, образец «=a==
» будет соответствовать последовательности «a=
».
Если в образце стоит некоторый символ имени, он соответствует любой последовательности, содержащей по крайней мере один символ и его имя заменяется на поставленную в соответствие последовательность везде в следующем блоке, аналогично параметрам в макроинструкции. Например:
match a-b, 0–7
{ dw a,b-a }
сгенерирует инструкцию «dw 0, 7–0
». Каждое имя всегда ставится в соответствие как можно меньшему количеству символов, оставляя оставшиеся, то есть:
match a b, 1+2+3 { db a }
имя «a
» будет соответствовать символу «1
», оставляя последовательность «+2+3
» в соответствие с «b
». Но, таким образом:
match a b, 1 { db a }
для «b
» ничего не остается, и блок вообще не будет обработан.
Блок кода, определенный директивой «match
» обрабатывается так же, как любая макроинструкция, поэтому здесь могут использоваться любые операторы, специфичные для макроинструкций.