При описании команд нам придется указывать, какие операнды в них допустимы, а какие - нет. ЯА сокращения подобного рода указаний. Мы сейчас введем обозначения, которыми затем будем пользоваться при описании команд.
Непосредственные операнды (т. е. задаваемые в самой команде) мы будем обозначать буквой i (от immediate, непосредственный), указывая за ней, сколько разрядов - 8 (байт), 16 (слово) или 32 (двойное слово) - отводится на него i команде. При этом отметим: запись Пб не означает, что операнд не может быть любым числом, в качестве Пб можно указать и операнд 0, и операнд 32000, лишь бы он занимал не более 16 разрядов. В ЯА непосредственные операнды записываются в виде константных выражений.
Регистры будем обозначать буквой r (от register), указывая за ней требуемый размер регистра: r8 - это байтовые регистры (АН, AL, ВН и т. п.), а r6 - регистры размером в слово (АХ, ВХ, SI и т. п.). При этом буквой г мы обозначаем только регистры общего назначения, сегментные же регистры мы будем обозначать как sr.
Если операнд находится в памяти, то в команде указывается адрес соответствующей ячейки. Такие операнды мы обозначаем буквой m (от memory, память) с указанием размера ячейки. В ЯА эти операнды задаются адресными выражениями.
Команды пересылки
В ПК достаточно много команд пересылки, здесь мы рассмотрим только две из них - MOV и XCHG. Кроме того, рассмотрим оператор PTR.
Команда MOV
В ПК есть машинные команды пересылки байта или слова (переслать одной командой двойное слово нельзя). Пересылаемая величина берется из команды, регистра или ячейки памяти (регистр или ячейку памяти записывать в команду, естественно, нельзя). Таких команд много, но в ЯА все не записываются одинаково:
|
пересылка (move): MOV opl,op2
Поэтому при программировании на ЯА можно считать, что имеется только команда пересылки. Ассемблер, проанализировав указанные в этой символьной команде операнды, сам выберет нужную машинную команду пересылки, которую и запишет в формируемую им машинную программу.
По команде MOV на место первого операнда пересылается значение второго операнда: opl:=op2. Флаги эта команда не меняет.
Примеры:
MOV АХ,500; А: =500
MOV BL,DH; BL:=DH
В команде MOV допустимы следующие комбинации операндов:
Из этой таблицы видно, что запрещены пересылки из одной ячейки памяти в другую, из одного сегментного регистра в другой, запись непосредственного операнда в сегментный регистр. Это обусловлено тем, что в ПК нет таких машинных команд. Если по алгоритму все же нужно такое действие, то оно реализуется в две команды, пересылкой через какой-нибудь несегментный регистр. Например, записать число 100 в сегментный регистр DS можно так:
MOV АХ,100
MOV DS,AX; DS:=100
Отметим также, что командой MOV нельзя менять содержимое сегментного регистра CS. Это связано с тем, что регистры CS и IP определяют адрес той команды программы, которая должна быть выполнена следующей, поэтому изменение любого из этих регистров есть ничто иное, как операция перехода, а не пересылка. Команда же MOV не реализует переход.
Как известно, в ПК числа размером в слово хранятся в памяти в "перевернутом" виде, а в регистрах - в нормальном, неперевернутом. Команда MOV учитывает это и при пересылке слов между памятью и регистрами сама "переворачивает" их:
Q DW 1234h; Q: 34h, Q+l: 12h
…
|
MOV AX,Q; AH=12h, AL=34h
По команде MOV можно переслать как байт, так и слово. А как узнать, что именно - байт или слово - пересылает команда? Не может ли получиться так, что мы хотели написать команду пересылки слова, а оказалось, что команда пересылает байт? Ответ такой: размер пересылаемой величины определяется по типу операндов, указанных в символьной команде MOV. Более точно ситуация здесь следующая.
Пусть, к примеру, имеются такие описания переменных:
X DB?;TYPE X = BYTE
Y DW?;TYPE Y = WORD
Как правило, в команде MOV легко узнается тип (размер) одного из операндов, он и определяет размер пересылаемой величины. Например:
Отметим, что здесь по второму операнду (0) нельзя определить, какого он размера: ноль может быть и байтом (ООh), и словом (0000h). Если можно определить размеры обоих операндов, тогда эти размеры должны coвпадать (либо байты, либо слова), иначе ассемблер зафиксирует ошибку. Например:
Отметим, что при пересылках никаких преобразований байта в слово или слова в байт не производится.