Примеры прерывающих подпрограмм
Некоторые особенности программирования для режима прерываний были описаны ранее на примере обработки аппаратных прерываний от таймера. Программирование работы с мышью имеет свои специфические особенности. Например, при обслуживании двухкнопочной мыши драйвер различает пять событий, но для их обработки он может вызвать только одну подпрограмму. Поэтому мы сначала рассмотрим подпрограмму, реагирующую только на одно событие – перемещение курсора, а затем обсудим, что делать с кнопками.
Способы перемещения курсора
Основные действия, выполняющие перемещение курсора, были описаны в соответствующем разделе на примере подпрограммы Motion. При работе в режиме прерываний задача должна иметь возможность запрещать перемещение курсора. Например, при построении нового рисунка изображение курсора временно удаляется с экрана. При этом подпрограмма не должна перемещать курсор. Задача может либо временно запрещать драйверу вызов прерывающей подпрограммы, либо устанавливать специальный признак, анализируемый при перемещении курсора.
Первый способ имеет следующий недостаток. В тот момент, когда задача удаляет изображение курсора с помощью подпрограммы Hidepnt, значения переменных winpnt, offspnt, Xpointer, Ypointer (см. пример 6.8) соответствуют значениям СПК внутреннего буфера драйвера. Если задача запретила драйверу вызывать подпрограмму перемещения курсора, а оператор в это время двигает мышь, то новые значения СПК не будут соответствовать значениям указанных переменных. Когда задача восстановит изображение курсора с помощью подпрограммы showpnt, то оно появится на старом месте. А после восстановления работы прерывающей подпрограммы, при первом движении мыши, курсор скачком переместится в новую позицию.
Второй способ избавлен от этого недостатка. Если установлен специальный признак, то прерывающая подпрограмма вычисляет текущие значения переменных winpnt, offspnt, xpointer, Ypointer, но не перемещает курсор. В результате значения этих переменных и СПК всегда будут соответствовать друг другу. Теперь, когда задача вызовет подпрограмму showpnt, изображение курсора появится на новом месте.
Подпрограмма Mousm
Текст подпрограммы, перемещающей курсор по прерываниям, приведен в примере 6.14. В нем использованы имена переменных curmp и pntstat, их следует добавить к описанным в примере 6.8, т. е. разместить в разделе данных задачи. Вполне достаточно, если они будут иметь размер байта. Советуем вам сравнить текст данной подпрограммы с описанным в примере 6.13.
Пример 6.14. Прерывающая подпрограмма для перемещения курсора.
Mousm: mov ах, data ax = значение сегмента данных mov ds, ах установка сегмента данных mov es, Vbuff установка сегмента видеобуфера inc curmp!! счетчик перемещений курсора mov Xpointer, ex сохранение нового значения mov Ypointer, dx сохранение нового значения mov ax, dx ах = номер строки mui horsize dx:ax = Ypointer*horsize add ax, ex прибавляем к ах номер столбца adc dx, 00 учитываем возможность переполнения xchg ax, dx переставляем содержимое ах и dx mov byte ptr GrUnit ах = al*GrUnit add ax, Base win!! учитываем значение базового окна test pntstat, 01 проверка состояния курсора je msmx › курсор удален с экрана call Hidepnt гасим курсор mov Offspnt, dx сохраняем смещение в Offspnt mov Winpnt, ax сохраняем в Winpnt call Showpnt рисуем курсор и выходим retf возвращение в драйвер rosmx: mov Offspnt, dx сохраняем смещение в Offspnt mov Winpnt, ax сохраняем в Winpnt retf возвращение в драйвер
Выполнение подпрограммы начинается с восстановления содержимого сегментных регистров ds и es, поскольку оно было изменено драйвером. Далее расположена команда, увеличивающая значение переменной curmp на 1. Она нужна для того, чтобы задача могла определить, перемещайся курсор или нет. Если при выполнении вашей задачи такая информация не нужна, то просто исключите команду из текста подпрограммы.
Затем новые значения координат присваиваются переменным xpointer н Ypointer и пересчитываются в адрес видеопамяти. В отличие от примера 6.13 вычисленные величины сразу не присваиваются переменным offspnt и winpnt, а сохраняются в регистрах dx и ах. Это делается потому, что значения указанных переменных можно изменять только после выполнения подпрограммы Hidepnt.
Перед вызовом Hidepnt проверяется состояние младшего разряда переменной pntstat. Если он установлен, то изображение курсора находится на экране, его можно удалять и перемещать. В противном случае содержимое регистров dx и ах сохраняется в переменных offspnt и winpnt и команда retf выполняет возврат в драйвер.
Таким образом, подпрограмма Mousm в любом случае изменяет значения переменных, указывающих координаты и адрес видеопамяти для изображения курсора, а само изображение перемещается только в том случае, когда установлен младший разряд переменной pntstat – признак нахождения курсора на экране.