- •Системное программирование
- •Контрольные вопросы
- •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 Кафедра Вычислительной Техники и Программирования Московского Государственного Открытого Университета
9. Упражнения
Пример 1. На языке ассемблера разработать подпрограмму пузырьковой сортировки массива. Элементами массива должны быть беззнаковые целые числа размером слово. Начальный адрес массива должен находиться в регистре DI, а количество элементов – в первом элементе.
Решение. Вариант реализации подпрограммы сортировки SORT приводится ниже. Для работы процедуры необходимы две вспомогательные переменные CNT и ADD, размером в слово. Их можно определить в сегменте данных (как показано ниже) или выделить место в стеке (по методу хранения локальных данных процедур). Первая переменная хранит счетчик числа сравнений, а вторая – начальный адрес массива в памяти.
При каждом проходе счетчик CNT уменьшается на единицу, чтобы на следующей итерации не сортировать несколько последних уже отсортированных («всплывших» на свое место) элементов. Когда счетчик обнулится, сортировка считается завершенной.
Процедура использует регистр BX в качестве флага обмена (в начале он установлен), а регистр AX – для хранения элемента, который будет сравниваться с последующим. Если последующий элемент меньше текущего, они меняются местами и флаг обмена BX сбрасывается, сигнализируя об обмене.
CNT DW ? ; счетчик числа сравнений
ADD DW ? ; начальный адрес массива
SORT PROC
PUSH AX
PUSH BX
PUSH CX
MOV CX, [DI] ; количество элементов массива
DEC CX ; число проходов 0..CX-1
MOV CNT, CX ; сохранить в памяти число проходов
PASS: MOV BX, 1 ; установить флаг обмена
DEC CNT ; очередное сравнение
JZ SORT ; сортировка завершена, если CNT = 0
MOV CX, CNT ; число сравнений в CX
MOV DI, ADD ; начальный адрес в DI
L: ADD DI, 2 ; переход к следующему элементу данных
MOV AX, [DI] ; сохранить элемент в AX
CMP [DI+2], AX ; сравнить элемент со следующим
JAE COUNT ; следующий элемент меньше текущего
XCHG [DI+2], AX ; обменять местами элементы
MOV [DI], AX
XOR BX, BX ; обнулить флаг обмена
COUNT: LOOP L ; проверить остальные элементы
CMP BX, 0 ; проверка на обмены
JE PASS ; обмены элементов были проведены
SORT: MOV DI, ADD ; восстанавливаем адрес начала списка
POP CX
POP BX
POP AX
RET
SORT ENDP
Пример 2. На языке ассемблера разработать подпрограмму бинарного поиска заданного элемента в упорядоченном массиве. Элементами массива должны быть беззнаковые целые числа размером слово. Искомый элемент должен быть помещен в регистр AX. Начальный адрес массива по-прежнему должен храниться в регистре DI, а количество элементов – в первом элементе.
Результат поиска должен быть возвращен через регистр SI и флаг CF: если значение не найдено флаг CF должен быть установлен в 1, а регистр SI содержать адрес последнего проверенного элемента; если поиск завершился успешно, флаг CF должен быть сброшен, а SI содержать адрес найденного элемента.
Решение. Процедура бинарного поиска BINSRCH приведена ниже (описание метода приведено в примере 4 главы 1). Она также использует вспомогательную переменнуюARR, содержащую начальный адрес массива. Первым действием алгоритма является проверка искомого элемента на выход за границы диапазона. Для этого значение регистра AX сравнивается с первым и последним элементами массива. Если условие выхода за диапазон выполняется, устанавливается флаг CF с помощью команды STC и процедуры завершает работу. В противном случае происходит переход по метке SRCH к началу поиска элемента.
Поскольку слова отстоят друг от друга на расстояние двух байт, при делении отрезка пополам полученный индекс приводится к четному значению. Поиск считается неудачно завершенным, если индекс уменьшился до 2. В начале поиска из первого элемента извлекается количество слов массива и дополняется до ближайшего четного значения.
Затем полученный индекс SI добавляется к адресу начала массива DI. В результате происходит перемещение указателя на середину массива. Средний элемент сравнивается с искомым. Если элемент не равен искомому, поиск продолжится в левой или в правой половине массива.
В обоих случаях проверяется индекс на равенство 2 (признак окончания поиска), выполнение деления индекса SI пополам и дополнение его до ближайшего четного значения. Однако при поиске в левой половине текущий индекс SI вычитается из текущего адреса DI, а при поиске в правой половине – складывается с ним.
ARRDW ? ; начальный адрес списка в памяти
BINSRCH PROC
CMP AX, [DI+2] ; сравнение искомого элемента с первым
JA LAST ; искомое значение превосходит первый элемент
LEA SI, [DI+2] ; иначе извлекаем адрес первого элемента
JE EXITF ; искомый элемент равен первому
STC ; устанавливаем флаг CF (элемент не найден)
EXITF: RET ; выход из подпрограммы
LAST:MOV SI, ES:[DI] ; определяем количество элементов
SHL SI, 1 ; умножаем на 2
ADD SI, DI ; перемещаем указатель на последний элемент
CMP AX, ES:[SI] ; сравнение искомого элемента с последним
JB SRCH ; искомый элемент меньше последнего
JE EXITL ; искомый элемент равен последнему
STC ; устанавливаем флаг CF (элемент не найден)
EXITL: RET ; выход из подпрограммы
SRCH:MOV ARR, DI ; сохранение в памяти адреса начала массива
MOV SI, [DI] ; определяем количество элементов
EVEN:TEST SI, 1 ; проверка на четность индекса
JZ ADDL ; да, индекс четный
INC SI ; приводим индекс к четному значению
ADDL:ADD DI, SI ; определяем индекс середины массива
CMPL:CMP AX, [DI] ; сравниваем искомый элемент со средним
JE EXIT ; если средний элемент равен искомому, выход
JA HIGH ; искомый элемент больше
CMP SI, 2 ; сравниваем индекс с 2
JNE SHRL ; индекс больше 2
NO:STC ; устанавливаем флаг CF (элемент не найден)
JE EXIT ; выход из подпрограммы
SHRL:SHR SI, 1 ; делим индекс пополам
TEST SI, 1 ; проверка на четность
JZ SUBL ; индекс четный
INC SI ; делаем индекс четным
SUBL:SUB DI, SI ; перемещаем указатель назад
JMP CMPL ; переход на очередную проверку
HIGH: CMP SI, 2 ; сравниваем индекс с 2
JE NO ; искомый элемент не найден
SHR SI, 1 ; делим индекс пополам
JMP EVEN
EXIT:MOV SI, DI ; сохраняем адрес последнего сравнения в SI
MOV DI, ARR; восстанавливаем адрес начала списка
RET ; выход из подпрограммы
BINSRCH ENDP