Последний и самый гибкий способ задания меток — это использование директивы «label
at
» и числовое выражение, определяющее адрес, на который данная метка должна ссылаться. Например, «label wchar word at char
» определяет новую метку для 16-битных данных по адресу «char
». Теперь инструкция «mov ax,[wchar]
» после компиляции будет выглядеть так же, как «mov ax,word [char]
». Если адрес не указан, директива «label
» будет ссылаться на текущий адрес. Таким образом, «mov [wchar],57568
» скопирует два байта, тогда как «mov [char],224
» скопирует один байт на тот же адрес.Метка, имя которой начинается с точки, обрабатывается как локальная, и её имя прикрепляется к имени последней глобальной метки (с названием, начинающемся с чего угодно, кроме точки) для создания полного имени этой метки. Так, вы можете использовать короткое имя (начинающееся с точки) где угодно перед следующей глобальной меткой, а в других местах вам придется пользоваться полным именем. Метки, начинающиеся с двух точек — исключения. Они имеют свойства глобальных, но не создают новый префикс для локальных меток.
«@@
@b
» (или эквивалент «@r
») ссылается на ближайшую предшествующую анонимную метку, а символ «@f
» ссылается на ближайшую после неё анонимною метку. Эти специальные символы нечувствительны к регистру.1.2.4 Числовые выражения
В предыдущих примерах все числовые выражения были обычными числами, константами или метками. Но они могут быть более сложными, использовать арифметические или логические операторы для вычисления во время компиляции. Все эти операторы с их значениями приоритета перечислены в таблице 1.4.
Операции с высшим приоритетом выполняются первыми, однако вы, конечно, можете изменить такой образ действий, заключив некоторые части выражения в скобочки. «+
-
", «*
» и «/
» — это стандартные арифметические операции, «mod
» вычисляет остаток от деления нацело. «and
», «or
», «xor
», «shl
», «shr
» и «not
» совершают те же логические операции, что и инструкции ассемблера с такими же названиями. «rva
» характерна только для формата вывода PE и производит превращение адреса в RVA.Числа в выражениях по умолчанию обрабатываются как десятичные, двоичные числа должны иметь «b
o
», шестнадцатеричные цифры должны начинаться символами «0x
» (как в языке C), или символом «$
» (как в языке Pascal) или должны заканчиваться буквой «h
». Также заключенная в кавычки строка при включении в выражение будет конвертирована в число — первый символ станет минимальным значащим байтом числа. Числовые выражения, используемые как значения адреса, могут также содержать любой из общих регистров, используемых для адресации, они могут быть сложены или умножены на подходящие значения так, как это позволено в инструкциях архитектуры x86.Также есть несколько специальных символов, которые могут быть использованы в числовом выражении. Первое — это «$
$$
» равно базовому адресу текущего диапазона адресов. Следующий символ — «%
» — это номер текущего повтора в частях кода, которые повторяются, благодаря использованию некоторых специальных директив (смотрите 2.2). Также существует символ «%t
», который всегда равен текущей отметке времени.Любое численное выражение также может состоять из одного значения с плавающей точкой (flat assembler не может производить во время компиляции операции с плавающей точкой) в научной записи. Для распознания компилятором, эти значения должны содержать в конце букву «f
.
» или «E
». Так, «1.0
», «1E0
» и «1f
» определяют одно и то же значение с плавающей точкой, когда как просто «1
» определяет целочисленное значение.1.2.5 Переходы и вызовы
Операнд любого перехода или инструкция вызова может предваряться не только операторами размера, но также одним из операторов, определяющих тип перехода: «near
far
». Например, если ассемблер в 16-битном режиме, инструкция «jmp dword [0]
» станет далеким переходом, а если ассемблер в 32-битном режиме, она станет близким переходом. Чтобы заставить эту инструкцию обрабатываться по-разному, используйте формы «jmp near dword [0]
» или «jmp far dword [0]
».