СОДЕРЖАНИЕ
2. Программная модель микропроцессора 8086
2.4. Способы задания операндов команды
3. Основные понятия языка ассемблера
3.2. Директивы определения данных
4. Сегментированная модель памяти
4.3. Общая структура программы
5.1. Соглашению по описанию команд
5.6. Команды организации циклов
5.11. Команды управления микропроцессором
7. Разработка одномодульной программы
7.1. Трансляция и компоновка программы
8. Разработка многомодульных программ
8.1. Принципы разработки модулей
8.2. Расширенное применение директивы сегментации
Программирование микропроцессорных устройств
10. Программирование системного таймера
10.1. Описание таймера-счетчика 8254
10.3. Структура регистров таймера
11. Программирование контроллера прерываний
11.1. Механизм обработки прерываний
11.4. Контроллер прерываний 8259
11.5. Идентификация прерываний
11.6. Прерывания bios и ms-dos
12. Программирование параллельного порта
12.2. Работа с параллельным портом на низком уровне
12.3. Стандартные средства работы с параллельным портом
13. Программирование последовательного порта
13.1. Основы последовательной передачи данных
13.2. Последовательный интерфейс rs-232c
13.3. Универсальный асинхронный приемо-передатчик 8250
13.4. Порты асинхронного адаптера
13.5. Стандартные средства программирования последовательного порта
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-ого элемента таблицы.
Особенности выполнения арифметических операций.Беззнаковые числа складываются по правилам двоичной арифметики. Однако факт переполнения разрядной сетки не фиксируется. Вместо этого единица переноса отбрасывается и в качестве ответа выдается искаженная сумма, а флаг CF устанавливается в 1 (если переноса не было, флаг обнуляется). Такое суммирование без учета единицы переноса называется суммированием по модулю 2k(k - размер ячейки):

При вычитании беззнаковых целых чисел при х у выполняется обычное вычитание. При х < у числу х дается заем единицы (к числу х прибавляется величина 2k) и затем производится вычитание. Ошибка не фиксируется, но флаг переноса CF устанавливается в 1. Такое вычитание называют вычитанием по модулю 2k:

Например, при k=8 вычитание 1-2 происходит таким образом:
(28+ 1) – 2 = (256 + 1) – 2 = 257 – 2 = 255
(в двоичной системе замена 1 на 256+1 есть замена 00000001 на 100000001, т.е. добавление 1 слева) и число 255 объявляется результатом вычитания.
Рассмотрим сложение и вычитание знаковых чисел. Если целые числа со знаком представлены в дополнительном коде, то складывать и вычитать их следует по алгоритмам беззнаковых чисел. Дополнительные коды знаковых операндов рассматривают как числа без знака и в таком виде их складывают или вычитают, а полученный результат затем рассматривают в дополнительном коде.
Например, пусть надо сложить +3 и -1 (ячейка 8 бит). Их дополнительные коды – 3 и (256-1)=255. Складываем числа как беззнаковые: 3+255 (mod 256) = 258 (mod 256) = 2. Величина 2 рассматривается как дополнительный код ответа, поэтому получаем ответ +2.
Таким образом, если знаковые числа представлены в дополнительном коде, то не нужны разные машинные команды для сложения и вычитания беззнаковых и знаковых чисел, достаточно одного набора команд. В этом и заключается преимущество дополнительного кода над другими способами представления знаковых чисел.
При представлении чисел (например, размером в байт) в дополнительном коде левый разряд является знаковым, а на модуль числа отводится 7 правых разрядов. При сложении возможно возникновение «переполнение мантиссы» – переход модуля числа (мантиссы) в знаковый разряд.
В общем случае переполнение мантиссы происходит, если слагаемые одного знака и сумма оказывается вне диапазона представимых знаковых чисел ([-128, +127] при k=8). Рассмотрим сложение знаковых чисел +127 и +2. Складывая их как беззнаковые числа 127 и 2, получим число 129, которое теперь надо рассматривать как дополнительный код ответа. Поскольку 129=256-127, то суммой должно быть число -127. В результате, складывая два положительных числа, получили отрицательное; ответ равен 129=10000001b и его модуль не помещается в 7 разрядов, поэтому он перешел в знаковый разряд, изменив его на противоположный.
Переполнение мантиссы возможно и при вычитании. Например, при вычитании (+127)-(-2) = 127+2 получаем 129, а это дополнительный код числа -127, которое и выдается как результат вычитания, хотя истинной разностью является число 129. Такое переполнение мантиссы фиксирует флаг переполнения OF: он устанавливается в 1, если переполнение имело место.
Таким образом, при сложении беззнаковых чисел, интерес представляет флаг переноса CF, но если складываются знаковые числа, то анализу подлежит флаг OF (переполнение мантиссы).
При сложении и вычитании чисел меняются также флаг нуля ZF и флаг знака SF. Флаг ZF устанавливается в 1, если результат оказался нулевым, и сбрасывается в 0, если результат ненулевой. Флаг SF содержит знаковый (самый левый) бит результата. Он полезен при работе со знаковыми числами, т.к. устанавливается в 1, если результат отрицательный, и сбрасывается 0 в противном случае.
Команды сложения и вычитания.Различают обычное двоичное сложение (вычитание), с учетом переноса (заема) и инкремент (декремент) операнда. Все эти команды применимы для выполнения операций над двоичными и двоично-десятичными числами. В последнем случае следующей командой должна обязательно следовать команда коррекции результата.
Команда ADDобеспечивает сложение двух 8- или 16-разрядных двоичных чисел (табл. 15). Результат помещается на место первого операнда. Флаги OF, SF, ZF, AF и PF устанавливаются в соответствии с результатом по обычным правилам. Флаг CF свидетельствует о наличии переноса из старшего разряда результата.
Табл. 15. Команда ADD.
|
Код |
Инструкция |
Описание |
|
00 /r |
ADD r/m8, r8 |
r/m8:= r/m8 + r8 |
|
01 /r |
ADD r/m16, r16 |
r/m16:= r/m16 + r16 |
|
02 /r |
ADD r8, r/m8 |
r8:= r8 + r/m8 |
|
03 /r |
ADD r16, r/m16 |
r16:= r16 + r/m16 |
|
04 ib |
ADD AL, imm8 |
AL:= AL + imm8 |
|
05 iw |
ADD AX, imm16 |
AX:= AX + imm16 |
|
80 /0 ib |
ADD r/m8, imm8 |
r/m8:= r/m8 + imm8 |
|
81 /0 iw |
ADD r/m16, imm16 |
r/m16:= r/m16 + imm16 |
|
83 /0 ib |
ADD r/m16, imm8 |
r/m16:= r/m16 + imm8 |
Примеры выполнения команды сложения:
MOV AL, 10 ; AL=10
ADD AL, 2 ; AL=AL+2=12
ADD AL, -12 ; AL=0 ZF=1
ADD AL, -10 ; AL=-10 SF=1
Командой ADD можно сложить числа размером в байт или слово. Сложение чисел другой размерности, например, двойных слов, приходиться реализовывать самостоятельно через сложение чисел размером в слово или байт. Здесь полезны команды ADC для сложения и SBB для вычитания.
Команда ADCобеспечивает сложение двух 8- или 16-разрядных двоичных чисел с учётом значения входного переноса (табл. 16). ФлагиOF,SF,ZF,AF,CFиPFустанавливаются по обычным правилам. ФлагCFсвидетельствует о наличии переноса из старшего разряда результата.
Табл. 16. Команда ADC.
|
Код |
Инструкция |
Описание |
|
10 /r |
ADCr/m8,r8 |
r/m8:=r/m8 +r8 +CF |
|
11 /r |
ADCr/m16,r16 |
r/m16:=r/m16 + r16 + CF |
|
12 /r |
ADC r8, r/m8 |
r8:= r8 + r/m8 + CF |
|
13 /r |
ADC r16, r/m16 |
r16:= r16 + r/m16 + CF |
|
14 ib |
ADC AL, imm8 |
AL:= AL + imm8 + CF |
|
15 iw |
ADC AX, imm16 |
AX:= AX + imm16 + CF |
|
80 /2 ib |
ADC r/m8, imm8 |
r/m8:= r/m8 + imm8 + CF |
|
81 /2 iw |
ADC r/m16, imm16 |
r/m16:= r/m16 + imm16 + CF |
|
83 /2 ib |
ADC r/m16, imm8 |
r/m16:= r/m16 + imm8 + CF |
Команда AAAкорректирует результат сложения двух неупакованных двоично-десятичных и ASCII чисел (табл. 17). Флаги AF и CF устанавливаются в соответствии с результатом операции. Значение флагов OF, SF, ZF и PF не определено.
Табл. 17. Команда AAA.
|
Код |
Инструкция |
Описание |
|
37 |
AAA |
Коррекция сложения неупакованных двоично-десятичных чисел. |
Складываемые числа располагаются в младших полубайтах операндов, причём один из них – в младшем полубайте регистра AL. Команда AAA используется после ADD, ADC или INC. Она корректирует результат в регистре AL на основании полученного результата и состояния флага вспомогательного переноса.