Синтаксис ассемблерных команд
Здесь и далее ассемблерными командами называются команды на языке встроенного ассемблера, вставляемые в тело ассемблерного оператора asm... end. Структура ассемблерной команды такова:
[Метка] [Префикс] [Код [Операнд [,Операнд]]]
В квадратных скобках указываются необязательные элементы структуры.
Метки
Любой команде ассемблерного оператора может предшествовать одна или несколько меток. В ассемблере используется два типа меток: глобальные и локальные. Глобальные метки - это обычные метки Турбо Паскаля. Они объявляются в разделе описаний после зарезервированного слова Label. С помощью глобальной метки можно передать управление в тело ассемблерного оператора оператором GOTO. Например:
Label
AltEnt;
begin
Goto AltEnd; {Передаем управление внутрь ассемблерного опера тора}
.......
asm
.......
AltEnd: {Сюда можно передать управление извне}
.......
end;
Локальные метки объявляются непосредственно в теле ассемблерного оператора. Эти метки обязаны начинаться символом «@». Поскольку этот символ нельзя использовать в именах Турбо Паскаля, он позволяет отличить локальную метку от глобальной. Локальная метка не известна нигде вне ассемблерного оператора, поэтому на нее нельзя передать управление оператором GOTO. По этой же причине в разных ассемблерных операторах можно использовать одноименные локальные метки.
Префиксы
Встроенный ассемблер поддерживает следующие префиксы команд:
LOCK Захват шины
REP/REPE/REPNE Повтор строковой команды
REPZ/REPNZ Синоним REPE/REPNE
SEGCS Перекрытие CS
SEGDS Перекрытие DS
SEGSS Перекрытие SS
SEGES Перекрытие ES
Префиксы LOCK/REP/REPE/REPNE описаны в п. 12.1.3. Префиксы SEGxx определяют сегментный регистр, который должен использоваться вместо умалчиваемого, и распространяются только на следующие за ними ассемблерные команды.
Если префикс указан без кода инструкции, он распространяет свое действие на следующую ассемблерную команду.
Код инструкции очень редко имеет более одного префикса и никогда - более трех: допускается следующая последовательность
LOCK SEGxx REPxx
Замечу, что если при обработке строковой команды произошло аппаратное прерывание, МП 8086/8088 «забывает» префиксы LOCK и SEGxx, которые, возможно, определены в той же команде, так что использовать сложные префиксные конструкции не рекомендуется.
Коды инструкций
Встроенный ассемблер поддерживает мнемонику всех команд, перечисленных в п.12.1.3. Кроме того, в ассемблерных командах может использоваться мнемоника инструкций процессора 8087, а также команды процессоров 80286/80287. Замечу, что инструкции 8087 допустимы только при активном состоянии {SN+}, 80286 - при {$G+}, a 80287 - в случае {$G+,N+}.
Операнды
Операндами встроенного ассемблера могут быть выражения, состоящие из комбинации регистров, констант, имен и символов операций.
Регистры
Во встроенном ассемблере используется мнемоника регистров, указанная в п. 12.1.1, а также имя ST для ссылки на регистры арифметического сопроцессора.
Константы
Ассемблер поддерживает строковые и числовые константы.
Строковые константы заключаются в апострофы или кавычки. Если константа объявлена с помощью кавычек, внутри нее символ апостроф рассматривается наравне с другими символами, т.е. не считается ограничителем константы, точно так же внутри константы, обрамленной апострофами, не считается ограничителем символ кавычки. Если внутри константы необходимо указать ограничивающий ее символ, он удваивается. Примеры:
'Строковая константа'
"Это - тоже строковая константа"
'Символ '' не считается ограничителем'
'внутри строки, обрамленной кавычками "..."'
Числовые константы могут быть только целыми и их значение не может превосходить емкости двойного слова, т.е. должно быть внутри диапазона
- 2 147 483 648...+ 4 294 967 295.
По умолчанию при записи числовых констант используется десятичная нотация, но ассемблер поддерживает также двоичные, восьмеричные и шестнадцатеричные константы. Двоичная константа составляется как комбинация единиц и нулей, заканчивающаяся символом В (от Binary - двоичный); при записи восьмеричной константы используются символы 0...7, а в ее конце ставится символ О (Octal - восьмеричный); шестнадцатеричная константа записывается по правилам Турбо Паскаля (начинается с символа #) либо по правилам Турбо Ассемблера: начинается с цифры, в конце ставится символ H (от Hexadecimal - шестнадцатеричный).
Имена
Локальные метки - это единственные имена, которые разрешается определять внутри ассемблерного оператора. Имена остальных объектов программы - констант, переменных, подпрограмм - должны определяться только с помощью средств Турбо Паскаля.
Область определения имен подчиняется тем же правилам, что и в Турбо Паскале -имена должны быть «видны» в том месте, где они используются, и они локализуются в пределах блока, в котором описаны.
Во встроенном ассемблере могут использоваться три предопределенных имени:
@@Code - текущий сегмент кода
@Data - начальный сегмент данных
@Result - ссылка внутри функции на ее результат
Имена @Code и @Data могут использоваться только в сочетании с директивой SEG для ссылки на нужный сегмент. Например:
asm
mov ax, SEG ©Data
mov ds,ax
end;
Имя @Result используется для присвоения результата функции. Например:
Function Min(X,Y: Integer): Integer;
{Эта функция сравнивает два целых числа и возвращает наименьшее из них)
begin
asm
mov ax,X {Помещаем Х в АХ}
cmp ax,Y {X<Y ?}
jl @ {Да - на выход}
mov ax,Y {Нет - помещаем Y в АХ}
@: mov ©Result,ax {АХ содержит результат}
end
end;
Для доступа к полям записей разрешается использование составных имен. Например:
type
Point = record X,Y: Integer
end;
Rect = record
A,B: Point
end;
var
P: Point;
R: Rect;
begin
asm
mov ax,P.X
add ax,P.Y
mov R.A.X,ax
end
end.
Идентификаторы типов можно применять к операндам для уточнения данных, о которых идет речь. Каждая из следующих команд реализует одно и то же действие: загружает в регистр АХ слово по адресу ES: [DI+4 ]:
mov ax,(Rect PTR es:[di]).В.Х
mov ax,Rect(es:[di]).В.Х
mov ax,esrRect[di].B.X
mov ax,Rect[es:di].B.X
mov ax,es:[di].Rect.B.X
Следующие имена не могут использоваться в операндах встроенного ассемблера:
- стандартные процедуры и функции (например, WriteLn, Chr);
- предопределенные массивы Mem, MemW, MemL, Port, PortW;
- константы с плавающей точкой, строковые и множественного типа;
- макросы (процедуры и функции, полностью реализуемые одним InLine-оператором);
- символ
- @Result вне функции.