Программирование аппаратных средств
Пример 3.12. Программирование мыши в режиме прерываний.
0.586; Будут команды новых процессоров code segment use16; 16-разрядное приложение assume CS: code,DS:code; Данные в сегменте команд main proc push CS; Настроим DS pop DS; на сегмент команд ;Сохраним обработчик прерываний последовательного порта mov AX,350Ch; Функция 35h, вектор 0Сh int 21h mov word ptr old_Oc,BX; Сохраним смещение mov word ptr old_Oc+2,ES; Сохраним сегмент ;Установим наш обработчик прерываний последовательного порта mov AX,25ОСb; Функция 25h, вектор 0Сh mov DX,offset new_0c; Адрес нашего обработчика int 21h ;Остановим программу функцией ввода с клавиатуры mov AH,01h int 21h ;Восстановим исходный обработчик драйвера мыши mov AX,250Ch; Функция 25h, вектор 0Сh Ids DX,old_0c; Сохраненный адрес int 21h mov AX,4C00h; Завершим программу int 21h main endp new_0c proc pusha; Сохраним все регистры push DS; Сегментные регистры не push ES; сохраняются командой pusha mov DX,3F8h; Порт данных in AL,DX; Прочитаем cmp AL, 60h; Левая клавиша – код 60h je Ibtn; Переход на отработку cmp AL, 5Oh; Правая клавиша – код 5Oh je rbtn; Переход на отработку ;Завершение обработчика прерываний outret:pop ES; Восстановим сегментные pop DS; регистры mov AL,20h; Команда EOI out 20h,AL; в контроллер прерываний рора; Восстановим все регистры iret; Выход из прерывания ;Если нажата левая клавиша мыши Ibtn: mov АН, 1Eh; Атрибут символов желтый по синему mov SI,offset msgdn; Адрес выводимой строки jmp commn; На общую часть вывода ;Если нажата правая клавиша мыши rbtn: mov AH,2Eh; Атрибут символов желтый по зеленому mov SI,offset msgdn; Адрес выводимой строки ;Общая часть вывода на экран диагностической строки commn: mov BX,OB800h; Настроим ES mov ES,BX; на видеобуфер push CS; Настроим DS pop DS; на наш сегмент mov CX,6; Число выводимых символов mov DI,2000; Смещение на экране cld; Движение вперед scr: lodsb; АL=очередной символ stosw; Из АХ на экран loop scr; Цикл jmp outret; После вывода завершить ;обработку прерывания new_0c endp old_0c dd 0; Ячейка для исходного вектора msgdn db "Левая!"; Выводимые сообщения msgup db "Правая" code ends stk segment stack dw 128 dup(O) stk ends end main
Приведенный пример с точки зрения его структуры построен обычным образом. Исходное содержимое вектора 0Ch сохраняется в ячейке old_0c и используется перед завершением программы для восстановления вектора. Для упрощения установки обработчика прерываний программа написана без сегмента данных; ее немногие данные размещены в сегменте команд. Поскольку в начале программы регистр DS настраивается на сегмент команд, адресация к данным (в основной программе) возможна через DS.
Для того, чтобы можно было наблюдать обработку прерываний от мыши, основная программа после выполнения инициализирующих действий останавливается с помощью функции 01h DOS ожидания ввода символа с клавиатуры. После нажатия любой клавиши программа завершается, восстановив предварительно исходное состояние вектора последовательного порта.