repeat 8
mov byte [bx],%
inc bx
end repeat
Сгенерированный код сохраняет байты со значениями от одного до восьми в памяти, адресованной регистром BX.
Количество повторений может быть равным нулю, и в таком случае инструкции не будут ассемболироваться вовсе.
«break
» позволяет остановить повторение раньше и продолжить ассемблирование с первой строки после «end repeat
». В сочетании с директивой «if
» она позволяет остановить повторение при выполнении некоторого особого условия, например:
s = x/2
repeat 100
if x/s = s
break
end if
s = (s+x/s)/2
end repeat
«while
» повторяет блок инструкций, пока выполняется следующее за ней условие, определенное логическим выражением. Блок инструкций для повторения должен заканчиваться директивой «end while
». Перед каждым повторением логическое выражение вычисляется и если его значение ложь, ассемблирование продолжается, начиная с первой строки после «end while
». Также в этом случае символ «%
» содержит номер текущего повторения. Директива «break
» может быть использована для остановки этого типа цикла так же, как с директивой «repeat
». Предыдущий пример может быть переписан с использованием «while
» вместо «repeat
» таким образом:
s = x/2
while x/s
s
s = (s+x/s)/2
if % = 100
break
end if
end while
Блоки, определенные с использованием «if
», «repeat
» и «while
» могут быть вложены в любом порядке, однако и закрыты в обратном. Директива «break» всегда останавливает обработку бока, который был начат последним либо директивой «repeat
», либо «while
».
2.2.3 Адресные пространства
«org
» устанавливает адрес, по которому следующий за ней код должен появиться в памяти. За ней должно следовать числовое выражение, указывающее адрес. Эта директива начинает новое адресное пространство, следующий код сам по себе никуда не двигается, но все метки, определенные в нем и значение символа «$
» изменяются как если бы он был бы помещен по этому адресу. Тем не менее обязанность поместить во время выполнения код по правильному адресу лежит на программисте.
«load
» позволяет определить константу двоичным значением, загруженным из уже сассемблированного кода. За директивой должно следовать имя константы, затем опционально оператор размера, затем оператор «from
» и числовое выражение, определяющее валидный адрес в текущем адресном пространстве. Оператор размера здесь имеет необычное значение — он определяет, сколько байтов (до 8) должно быть загружено из двоичного значения константы. Если оператор размера не определен, загружается один байт (таким образом значение оказывается в пределах от 0 до 255). Загруженные данные не могут превосходить текущее смещение.
«store
» может модифицировать уже сгенерированный код заменой некоторых ранее сгенерированных байтов значением, задаваемым следующим за инструкцией числовым выражением. Перед этим выражением может идти оператор размера, определяющий, насколько длинное значение оно задает, то есть сколько будет сохранено байт. Если оператор размера не задан, подразумевается длина в один байт. Далее должен следовать оператор «at
» и числовое выражение, указывающее валидный адрес в текущем адресном пространстве кода. По этому адресу будет сохранено задаваемое значение. Это директива для продвинутого применения и её следует использовать осторожно.
Обе директивы «load
» и «store
» ограничены оперированием только в пределах текущего адресного пространства. Символ «$$
» всегда равен базовому адресу в текущем адресном пространстве, а символ «$
» — это адрес текущей позиции в нём, то есть эти два значения определяют границы действия директив «load
» и «store
».
Сочетая директивы «load
» и «store
» можно делать вещи, такие как шифрование некоторого из уже сгенерированного кода. Например, для шифрования всего кода, сгенерированного в текущем адресном пространстве вы можете использовать такой блок директив:
repeat $-$$
load a byte from $$+%-1
store byte a xor c at $$+%-1
end repeat
и каждый байт коза будет проксорен со значением, определенным константой «c
».