Команды пересылки данных
Команда MOVпересылает содержимое источника (второго операнда) на место приёмника (первого операнда) (табл. 5.10). Флаги команда не изменяет. Пересылаемая величина извлекается из команды, регистра или ячейки памяти, а записывается в регистр или ячейку памяти. Пересылать одной командой двойное слово запрещено.
Инструкции с кодами операций 8C и 8E обеспечивают загрузку и извлечение информации из сегментных регистров. Занесение информации в регистр CS запрещено, т.к. регистровая пара CS:IP определяет адрес команды, которая должна быть выполнена следующей. Поэтому для этой цели необходимо использовать любую инструкцию дальнего (межсегментного) перехода (см. раздел 5.5).
Табл. 10. Команда MOV.
Код | Инструкция | Описание |
88 /r | MOV r/m8, r8 | Пересылка из r8 в r/m8. |
89 /r | MOV r/m16, r16 | Пересылка из r16 в r/m16. |
8A /r | MOV r8, r/m8 | Пересылка из r/m8 в r8. |
8B /r | MOV r16, r/m16 | Пересылка из r/m16 в r16. |
8C /r | MOV r/m16, Sreg | Пересылка из Sreg в r/m16. |
8E /r | MOV Sreg, r/m16 | Пересылка из r/m16 в Sreg. |
A0 ow | MOV AL, m8 | Пересылка из m8 в AL. |
A1 ow | MOV AX, m16 | Пересылка из m16 в AX. |
A2 ow | MOV m8, AL | Пересылка из AL в m8. |
A3 ow | MOV m16, AX | Пересылка из AX в m16. |
B0+rb | MOV r8, imm8 | Пересылка imm8 в r8. |
B8+rw | MOV r16, imm16 | Пересылка imm16 в r16. |
C6 /0 | MOV r/m8, imm8 | Пересылка imm8 в r/m8. |
C7 /0 | MOV r/m16, imm16 | Пересылка imm16 в r/m16. |
Командой MOV запрещена также пересылка из одной ячейки памяти в другую, из одного сегментного регистра в другой и запись непосредственного операнда в сегментный регистр. Если по алгоритму такое действие требуется выполнить, оно реализуется путем пересылки данных через несегментный регистр.
Например, записать число 100 в сегментный регистр DS можно так:
MOV АХ, 100
MOV DS, AX
Как правило, в команде MOV легко определить тип одного из операндов и размер пересылаемой величины, например:
MOV АХ, 300 ; пересылка слова
MOV AH, AL ; пересылка байта
В ряде случаев по операндам команды MOV нельзя определить размер пересылаемой величины. Пусть в регистре AX находится адрес некоторой ячейки памяти и требуется записать 0 в эту ячейку. Такое обнуление можно сделать с помощью команды:
MOV [AX], 0
Однако по этой команде нельзя определить, какого размера пересылаемый ноль, поскольку второй операнд может обозначать ноль размером в байт (00h) или размером в слово (0000h). Кроме того, адрес из регистра AX может быть также адресом ячейки как размером в байт, так и размером в слово (с одного и того же адреса могут начинаться ячейки разных размеров). Поэтому ассемблер зафиксирует ошибку, сообщая, что типы операндов неизвестны.
Для явного указания типов операндов команды используется оператор указания типа PTR:
<тип> PTR <выражение>
где <тип> – BYTE, WORD или DWORD, выражение может быть константным или адресным.
Если указано константное выражение, то оператор сообщает, что значение выражения (число) должно рассматриваться как величина указанного типа (размера); например, BYTE PTR 0 – ноль как байт, а WORD PTR 0 – ноль как слово.
Если в PTR указано адресное выражение, то оператор сообщает, что адрес, являющийся значением выражения, должен восприниматься ассемблером как адрес ячейки указанного типа, например: WORD PTR A – адрес A обозначает слово (байты с адресами A и A+1).
Вернемся к нашему примеру и запишем его корректно с использованием оператора PTR. При обнулении байта по адресу из регистра AX, то команда имеет вид:
MOV BYTE PTR [AX], 0 или MOV [AX], BYTE PTR 0
Если требуется переслать нулевое слово:
MOV WORD PTR [AX], 0 или MOV [AX], WORD PTR 0
Обычно принято уточнять тип операнда-адреса, а не тип непосредственного операнда.
Перестановку двух величин можно реализовать с помощью команды MOV, однако существует и специальная команда XCHG(табл. 11). Инструкция меняет местами содержимое своих операндов. Флаги команда не меняет.
Табл. 11. Команда XCHG.
Код | Инструкция | Описание |
90+rw | XCHG AX, r16 | AX ↔ r16 |
90+rw | XCHG r16, AX | r16 ↔ AX |
86 /r | XCHG r/m8, r8 | r/m8 ↔ r8 |
86 /r | XCHG r8, r/m8 | r8 ↔ r/m8 |
87 /r | XCHG r/m16, r16 | r/m16 ↔ r16 |
87 /r | XCHG r16, r/m16 | r16 ↔ r/m16 |
Например, для обмена содержимого регистров AX и BX следует записать:
MOV АХ, 124
MOV BX, 43
ХСHG AX, BX ; АХ=43, BX=124
Перестановка содержимого двух ячеек памяти недопустима. Если требуется провести такую перестановку, она реализуется через регистр. Следующий пример меняет местами значения байтовых переменных X и Y:
MOV AL, X ; AL=X
XCHG AL, Y ; AL=Y, Y=X
MOV X, AL ; X=Y (исходное значение)
Рассмотрим еще несколько примеров команды MOV:
A DW 10 DUP(0) ; одномерный массив A из 10-ти элементов размером слово
B DW A ; в переменной B хранится адрес переменной A
...
MOV BX, B ; помещение в регистр BX адреса 1-ого элемента
MOV DX, [BX] ; помещение в регистр DX значения переменной A
MOV AX, BX ; помещение в регистр AX адреса 1-ого элемента A
...
MOV BX, 4 ; индекс второго элемента массива
MOV DX, A[BX] ; модификация адреса по регистру BX
Модификация адреса может быть выполнена и для двумерного массива. Например, для матрицы 10x10:
A DW 10 DUP(10 DUP (0))
запись элемента [i,j] в регистр AX будет следующей (регистры SI и DI содержат индексы):
MOV AX, A[SI][DI]
Следует заметить, что следующие записи эквиваленты (A и B – некоторые регистры-модификаторы):
[A][B] = [A]+[B] = [A+B]
В рассмотренном примере для получения адреса переменной A мы ввели дополнительную переменную B. Однако для загрузки исполнительного адреса операнда в памяти существует специальная команда LEA(табл. 12). Полученный результат заносится в регистр общего назначения. Флаги команда не изменяет. В качестве первого операнда команды должен быть указан регистр общего назначения, а в качестве второго – адресное выражение.
Табл. 12. Команда LEA.
Код | Инструкция | Описание |
8D /r | LEA r16, m | Загрузка в r16 исполнительного адреса ячейки m. |
Команда LEA может ссылаться на операнд источника с помощью любого типа адресации, который можно указать байтом ModRegR/M. Поля Mod и R/M байта ModRegR/M используются при вычислении адреса. Поле Reg этого байта определяет регистр общего назначения, в который должен быть занесён адрес.
Во многих случаях команда LEA идентична команде MOV с непосредственным операндом. Например, следующие две команды выполняют одинаковое действие:
MOV BX, OFFSET A
LEA BX, A
В первом случае выполняется непосредственная пересылка, которая использует смещение переменной A относительно начала сегмента данных. Оператор OFFSET сообщает транслятору, что в регистр BX надо загрузить смещение адресного значения переменной A. Команда LEA вычисляет действительный адрес переменной A и помещает его в регистр BX.
Для загрузки в регистр BX адреса десятого байта массива, на который указывает регистр DI. Пример применение команды LEA следующий:
LEA BX, 10[DI]
Ассемблер обратится по адресу содержимого регистра DI, добавит смещение 10, и затем поместит это значение (адрес) в регистр BX. Аналогичной команды с непосредственным операндом MOV для выполнения той же функции не существует.
Механизм адресации микропроцессора 8086 требует определения сегмента и смещения каждой переменной. Такое действие можно выполнить с помощью команд загрузки дальнего указателя LDSи LES(табл. 13). По команде LDS (LES) в сегментный регистр DS (ES) и в указанный регистр общего назначения загружается дальний указатель, значение которого находится в указанной области памяти. Флаги команда не изменяет.
Табл. 13. Команды загрузки дальнего указателя.
Код | Инструкция | Описание |
C5 /r | LDS r16, m16:16 | Загрузка дальнего указателя в DS:r16. |
C4 /r | LES r16, m16:16 | Загрузка дальнего указателя в ES:r16. |
Например, команда:
LDS SI, A
загружает регистровую пару DS:SI значениями сегмента и смещения, содержащимися в переменной A: в регистр SI помещается смещение, расположенное по адресу A, а в регистр DS – значение сегмента, расположенное по адресу A+2.
И последняя инструкция, используемая в операциях модификации адресов, XLAT(табл. 14). Инструкция перекодирует по таблице значение регистра AL. Команда помещает в регистр AL содержимое байта памяти по адресу, равному сумме содержимого регистров BX и AL. Флаги команда не меняет. Команда используется при перекодировке символов.
Табл. 14. Команда XLAT.
Код | Инструкция | Описание |
D7 | XLAT | AL:= [BX+AL] |
Предположим, имеется таблица кодировки символов размером до 256 байтов, и i-й элемент рассматривается как новый код символа с кодом i. Если начальный адрес таблицы поместить в регистр BX, а исходный код перекодируемого символа в регистр AL, то команда XLAT поместит в регистр AL новый код символа из i-ого элемента таблицы.