- •1. Основы программирования для dos 9
- •1.1.7. Средства bios 21
- •2. Приемы системного программирования 57
- •Введение
- •1.Основы программирования для dos
- •1.1. Структура и выполнение программ в dos
- •Программа типа сом
- •Программа типа ехе
- •1.2.Использование служебных функций dos и bios
- •1.3.Вывод на экран в текстовом режиме
- •Средства dos
- •Средства bios
- •Выбор видеорежима
- •Управление положением курсора
- •Вывод символов на экран
- •Прямая работа с видеопамятью
- •1.4.Ввод с клавиатуры
- •Средства dos
- •Средства bios
- •1.5.Графические видеорежимы
- •Работа со стандартными графическими режимами
- •Работа с svga-режимами
- •(Продолжение таблицы 4)
- •(Окончание таблицы 4)
- •1.6.Работа с мышью
- •1.7.Другие устройства
- •Системный таймер
- •Последовательный порт
- •Параллельный порт
- •1.8.Работа с файлами
- •Создание и открытие файлов
- •Чтение из файла и запись в файл
- •Закрытие и удаление файла
- •Поиск файлов
- •Управление файловой системой
- •1.9.Управление памятью
- •Обычная память
- •Область памяти umв
- •Область памяти нма
- •Интерфейс ems
- •Интерфейс xms
- •1.10.Организация процессов
- •Запуск программ на выполнение
- •Переменные окружения
- •Командные параметры
- •2.Приемы системного программирования
- •2.1.Управляющие структуры
- •Структуры if... Then... Else
- •Структуры case
- •Конечные автоматы
- •2.2.Процедуры и функции
- •Передача параметров
- •Передача параметров по значению
- •Передача параметров по ссылке
- •Передача параметров по возвращаемому значению
- •Передача параметров по результату
- •Передача параметров по имени
- •Передача параметров отложенным вычислением
- •Передача параметров в регистрах
- •Передача параметров в глобальных переменных
- •Передача параметров в стеке
- •Передача параметров в потоке кода
- •Передача параметров в блоке параметров
- •Локальные переменные
- •2.3.Обработка прерываний
- •Обработчики прерываний
- •Прерывания от внешних устройств
- •Взаимодействие прикладных и системных обработчиков прерываний
- •2.4.Резидентные программы
- •Системные средства организации резидентных программ
- •Взаимодействие с резидентной программой
- •2.5.Драйверы устройств в dos
- •Литература
Обработчики прерываний
Вызов программных прерываний осуществляется синхронно, то есть на момент возникновения прерывания точно определено программное состояние системы. Кроме того, при этом не используется контроллер прерываний и специфические особенности устройств. В силу этого структура обработчика программного прерывания оказывается простой. Пример обработчика программного прерывания, обнуляющего регистр AX:
int_handler proc far
mov ax, 0
iret
int_handler endp
После того как обработчик написан, следующий шаг — привязка его к выбранному номеру прерывания. Это можно сделать, прямо записав его адрес в таблицу векторов прерываний, однако лучше пользоваться специальными функциями DOS для работы с векторами:
Функция DOS 25h — Установить вектор прерывания
Ввод: АН = 25h
АL = номер устанавливаемого вектора
DS:DX = адрес обработчика прерывания
Вывод: нет
Функция DOS 35h — Получить содержимое вектора прерывания
Ввод: АН = 35h
АL = номер вектора (прерывания)
Вывод: ES:BX = содержимое вектора (адрес обработчика прерывания)
Установка обработчика из примера выше будет выглядеть так:
mov ah, 25h ; установить обработчик
mov al, 87h ; прерывания 87h
mov dx, seg int_handler ; сегментный адрес
mov ds, dx ; в DS
mov dx, offset int_handler ; смещение в DX
int 21h
Теперь команда INT 87h будет вызывать наш обработчик, то есть приводить к записи 0 в регистр АХ.
Перед завершением работы программа должна восстановить все старые обработчики прерываний, даже если это были неиспользуемые прерывания типа 87h, иначе обращение по этим векторам после выгрузки обработчика приведет к нарушению работы ОС. Для этого надо перед предыдущим фрагментом кода сохранить адрес старого обработчика, так что полный набор действий для программы, перехватывающей прерывание 87h, будет выглядеть следующим образом:
; скопировать адрес предыдущего обработчика в переменную old_handler
mov ax, 3587h ; АН = 35h, AL = номер прерывания
int 21h ; считать адрес обработчика прерывания
mov word ptr old_handler, bx ; сохранить смещение
mov word ptr old_handler+2, es ; и сегментный адрес
; установить наш обработчик
mov ax, 2587h ; АН = 25h, AL = номер прерывания
mov dx, seg int_handler
mov ds, dx
mov dx, offset int_handler
int 21h
, восстановить предыдущий обработчик
Ids dx, old_handler ; сегментный адрес в DS и смещение в DX
mov ax, 2587h
int 21h
При помощи собственных обработчиков исключений можно обрабатывать особые ситуации (исключения), которые могут происходить в программе, например деление на ноль. В реальном режиме можно столкнуться всего с шестью исключениями:
#DE (деление на ноль) — INT 0 — ошибка, возникающая при переполнении и делении на ноль. Как для любой ошибки, адрес возврата указывает на ошибочную команду.
#DB (прерывание трассировки) — INT 1 — ловушка, возникающая после выполнения каждой команды, если флаг TF установлен в 1. Используется отладчиками, действующими в реальном режиме.
#OF (переполнение) — INT 4 — ловушка, возникающая после выполнения команды INTO, если флаг OF установлен.
#ВС (переполнение при BOUND) — INT 5 — ошибка, возникающая при выполнении команды BOUND.
#UD (недопустимая команда) — INT 6 — ошибка, возникающая при попытке выполнить команду, отсутствующую на данном процессоре.
#NM (сопроцессор отсутствует) — INT 7 — ошибка, возникающая при попытке выполнить команду FPU, если FPU отсутствует.