Постоянные выражения можно использовать там же, где допускается использование постоянных значений (констант). Турбо Ассемблер поддерживает полное вычисление выражений, включая вложенные скобки, арифметические, логические операции и операции отношения, а также множество операций, предназначенных для таких целей, как выделение для меток сегмента и смещения и определение размера переменных в памяти.
Например, во фрагменте программы:
MemVar DB 0
NextVar DB ?
mov ax,SEG MemVar
mov ds,ax
mov bx,OFFSET MemVar + (3*2) — 5)
mov BYTE PTR [bx],1
операция SEG используется для загрузки постоянного значения сегмента, в котором находится MemVar, и копирования этого значения из регистра AX в DS. Далее в этой программе используется сложное выражение, включающее в себя операции *, +, — и OFFSET, при вычислении которого получается значение OFFSET MemVar+1, которое представляет собой ни что иное, как адрес NextVar. Наконец, для выбора байтовой операции при сохранении константы 1 в ячейке, на которую указывает регистр BX (что представляет собой NextVar), используется операция BYTE PTR.
Относительно выражений стоит сделать важное замечание: при вычислении всех выражений должно получаться значение-константа. OFFSET MemVar — это значение-константа, представляющее собой сме-щение переменной MemVar в ее сегменте. Кроме того, в то время как сохраненное в переменной MemVar значение может изменяться, сама переменная MemVar, конечно, никуда не перемещается.
Так как значения-константы точно известны, Турбо Ассемблер может вычислять состоящие из постоянных значений выражения так же, как он ассемблирует ваш исходный код. Для Турбо Ассемблера выражение OFFSET MemVar + 2 совершенно аналогично выражению 5 + 2. Поскольку все элементы выражения неизменяемы и определены во время ассемблирования, выражение можно свести к одному значению-константе.
В выражениях могут использоваться следующие операции:
<>, (), LENGTH, MASK, SIZE, WIDTH
. (селектор элемента структуры)
HIGH, LOW
: (переопределение сегмента)
OFFSET, PTR, SEG, THIS, TYPE *, /, MOD, SHL, SHR +, — (бинарные)
EQ, GE, GT, LE, LT, NE
NOT
AND
OR, XOR
LARGE, SHORT, SMALL, .TYPE
Названия и обозначения некоторых операций говорят сами за себя. Эти операции выполняют в арифметических выражениях именно те действия, для которых они предназначены. Операции мы поясним в этой главе позднее, когда до них дойдет дело. Кроме того, ответы на вопросы, касающиеся отдельных операций, можно найти в Главе 2 «Справочного руководства».
Операнды-метки
Во многих инструкциях в качестве операндов можно использовать метки. При указании их в соответствующих операциях метки мо-гут использоваться для получения постоянных значений (констант).
Например:
MemWord DW 1
mov al,SIZE MemWord
Здесь значение 2 (размер в байтах переменной в памяти MemWord) помещается в AL. В данном контексте метка может становиться частью выражения, как уже показано в предыдущем разделе.
Метки могут также использоваться в качестве целевых операн-дов в операциях CALL и JMP. Например, во фрагменте программы:
cmp ax,100
ja IsAbove100
IsAbove100:
инструкция JA используется для перехода по адресу, заданному операндом IsAbove100, если значение AX превышает 100. Здесь метка используется в качестве константы, задавая адрес перехода.
Наконец, метки можно использовать в качестве операндов почти также, как используются регистры, то есть как операнд-источник или операнд-приемник в инструкциях работы с данными. Программа:
TampVar DW ?
mov [TempVar],ax
sub ax,[TempVar]
обнуляет содержимое регистра AX, так как первая инструкция записывает содержащееся в регистре AX значение в переменную памяти TempVar, затем вторая инструкция вычитает из AX сохраненное в TempVar значение.
Использование меток в качестве операндов представляет собой отдельную тему при описании моделей памяти. Этого мы коснемся позднее.
