- •Системное программирование
- •Контрольные вопросы
- •2. Программная модель микропроцессора 8086
- •2.1. Представление информации
- •2.2. Регистры микропроцессора
- •2.3. Формат машинной команды
- •2.4. Способы задания операндов команды
- •Контрольные вопросы
- •3. Основные понятия языка ассемблера
- •3.1. Предложения
- •3.2. Директивы определения данных
- •3.3. Выражения
- •Контрольные вопросы
- •4. Сегментированная модель памяти
- •4.1. Сегментирование адресов
- •4.2. Директивы сегментации
- •4.3. Общая структура программы
- •4.4. Модели памяти
- •Контрольные вопросы
- •5. Основные группы команд
- •5.1. Соглашению по описанию команд
- •5.2. Команды пересылки данных
- •5.3. Арифметические команды
- •5.4. Логические команды
- •5.5. Команды переходов
- •5.6. Команды организации циклов
- •5.7. Команды обработки строк
- •5.8. Стековые команды
- •5.9. Команды ввода-вывода
- •5.10. Команды прерываний
- •5.11. Команды управления микропроцессором
- •Контрольные вопросы
- •6. Подпрограммы
- •Контрольные вопросы
- •7. Разработка одномодульной программы
- •7.1. Трансляция и компоновка программы
- •7.2. Отладка программы
- •Контрольные вопросы
- •8. Разработка многомодульных программ
- •8.1. Принципы разработки модулей
- •8.2. Расширенное применение директивы сегментации
- •9. Упражнения
- •Контрольные вопросы
- •Программирование микропроцессорных устройств
- •10. Программирование системного таймера
- •10.1. Описание таймера-счетчика 8254
- •10.2. Режимы работы таймера
- •10.3. Структура регистров таймера
- •10.4. Упражнения
- •Контрольные вопросы
- •11. Программирование контроллера прерываний
- •11.1. Механизм обработки прерываний
- •11.2. Типы прерываний
- •11.3. Приоритеты прерываний
- •11.4. Контроллер прерываний 8259
- •11.5. Идентификация прерываний
- •11.6. Прерывания bios и ms-dos
- •11.7. Упражнения
- •Контрольные вопросы
- •12. Программирование параллельного порта
- •12.1. Интерфейс Centronics
- •12.2. Работа с параллельным портом на низком уровне
- •12.3. Стандартные средства работы с параллельным портом
- •12.4. Упражнения
- •Контрольные вопросы
- •13. Программирование последовательного порта
- •13.1. Основы последовательной передачи данных
- •13.2. Последовательный интерфейс rs-232c
- •13.3. Универсальный асинхронный приемо-передатчик 8250
- •13.4. Порты асинхронного адаптера
- •13.5. Стандартные средства программирования последовательного порта
- •13.6. Упражнения
- •Контрольные вопросы
- •Литература
- •141 Кафедра Вычислительной Техники и Программирования Московского Государственного Открытого Университета
5.2. Команды пересылки данных
Команда 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-ого элемента таблицы.