Графические устройства



 

Функции драйвера

Для того чтобы при изменении состояния мыши драйвер мог прервать выполнение задачи, последняя должна с помощью специальных функций установить прерывающую подпрограмму. В данном разделе описаны варианты установки и удаления прерывающих подпрограмм, требования к их оформлению, условия вызова и данные, передаваемые драйвером.

Обычно термин "прерывающая" указывает на то, что подпрограмма вызывается при возникновении событий, независящих от выполнения основной задачи полностью или частично. В нашем случае момент вызова подпрограммы зависит от действий оператора, работающего с мышью.

Особенность описываемых ниже подпрограмм заключается в том, что в случае необходимости их может вызывать основная задача, но это уже относится к области трюков или искусства программирования.

Установка основной подпрограммы

Драйвер может обслуживать только одну основную прерывающую подпрограмму. Для ее установки задаются адрес точки входа и маска события (или событий), при каждом наступлении которого (которых) будет вызываться установленная подпрограмма.

Функция 0С (set Event Handler) предназначена для установки подпрограммы, реагирующей на события, связанные с изменением состояния мыши. Перед обращением к драйверу полный адрес точки входа указывается в регистрах es:dx, а код маски помещается в младший байт регистра сх. Состояние его разрядов (0 или 1) соответствует наличию или отсутствию следующих событий:

разряд 0 — перемещение мыши;  
разряд 1 — левая кнопка нажата; разряд 2 — левая кнопка отпущена;
разряд 3 — правая кнопка нажата; разряд 4 — правая кнопка отпущена;
разряд 5 — средняя кнопка нажата; разряд 6 — средняя кнопка отпущена.

Допустимо произвольное сочетание указанных признаков, в частности, при записи в регистр сх кода 7Fh подпрограмма будет вызываться при любых изменениях состояния мыши.

Особым случаем является очищенное состояние регистра сх при обращении к драйверу, оно запрещает обслуживание ранее установленной подпрограммы. При изменении состояния мыши драйвер проверяет, указан код произошедшего события в маске или нет. Ни одно из событий не имеет код 0, поэтому при очищенной маске вызов подпрограммы исключается. Для очистки маски достаточно выполнить следующие две команды:

хоr сх, сх ; очистка регистра сх
Mouse ОС ; запрос функции ОС

Если ваша задача устанавливала прерывающую подпрограмму, то не забудьте выполнить эти две команды перед возвратом в DOS. В противном случае при первом же наступлении соответствующего события драйвер обратится к тому участку памяти, в котором подпрограммы уже нет, и возникнет аварийная ситуация.

При исполнении функции ос драйвер просто копирует содержимое регистров сх, dx и es в три слова внутреннего буфера, не выполняя никаких проверок. Таким простым способом исключается возможность установки нескольких подпрограмм. В любой момент времени драйвер обслуживает только ту подпрограмму, которая была установлена последней и "обмануть" его невозможно.

Если задача должна реагировать на несколько разных событий, то в маске надо установить соответствующие разряды, а в прерывающей подпрограмме уточнять причину (или причины) прерывания. Другими словами, иногда приходится сочетать режимы прерываний и опроса состояния драйвера мыши.

Функция 14 (Exchange Event Handier) выполняет те же действия, что и функция ос, кроме того, драйвер возвращает в регистрах es:dx адрес ранее установленной подпрограммы, а в регистре сх маску событий, на которые она реагировала. Эта функция может быть полезна в тех случаях, когда по каким-то причинам надо заменить прерывающую подпрограмму, а через некоторое время восстановить ее работоспособность.

Установка альтернативных подпрограмм

Учитывая, что основная подпрограмма может быть только одна, разработчики предусмотрели возможность установки трех альтернативных подпрограмм. Их принципиальное отличие в том, что в момент изменения состояния мыши должна быть нажата хотя бы одна из трех специальных клавиш.

Функция 18 (set Alternate Event Handier) устанавливает альтернативную подпрограмму, реагирующую на изменения состояний мыши при условии, что нажата одна из трех клавиш — <Alt>, <Ctrl>, <Shift>, или любая их комбинация. Перед обращением к драйверу полный адрес подпрограммы указывается в регистрах es:dx, а код маски помещается в младший байт регистра сх. Состояние его разрядов (0 или 1) соответствует наличию или отсутствию следующих событий:

разряд 0 — перемещение мыши; разряд 1 — левая кнопка нажата;
разряд 2 — левая кнопка отпущена; разряд 3 — правая кнопка нажата;
разряд 4 — правая кнопка отпущена; разряд 5 — нажата клавиша <Shift>;
разряд 6 — нажата клавиша <Ctrl>; разряд 7 — нажата клавиша <Alt>.

Три старших разряда маски отведены для указания одной из клавиш или их сочетания. Драйвер анализирует их не независимо друг от друга, а как трехразрядный код. Поэтому установка любых двух старших разрядов соответствует одновременному нажатию двух клавиш, а установка трех разрядов одновременному нажатию трех клавиш <Alt>+<Ctrl>+<Shift>.

Указание в коде маски, по крайней мере, одной клавиши обязательно. Если очищены все три старших разряда кода маски, то драйвер отвергает попытку установить подпрограмму. При этом он возвращает в регистре ах код OFFFFh.

Коды событий, связанных с изменением состояния мыши, занимают в маске пять младших разрядов, места для средней кнопки не хватает. Если установлены все младшие разряды, то подпрограмма будет вызываться при любом изменении состояния мыши, если одновременно нажата клавиша, указанная в старших разрядах кода маски.

Например, если код маски 9Fh, то подпрограмма будет вызываться, если нажата клавиша <Alt> и мышь перемещается, либо изменяется состояние ее левой или правой кнопок.

Особым случаем является очищенное состояние пяти младших разрядов кода маски, оно запрещает обслуживание установленной альтернативной подпрограммы. Обращаем ваше внимание на то, что должны быть очищены только пять младших разрядов. Например, если подпрограмма работала с клавишей <АН>, то для ее запрета выполняются две следующие команды:

mov сх, 8Oh ; код маски при работе с клавишей <Alt> Mouse 18 ; запрос функции 18

Перед завершением задачи надо обязательно запретить обслуживание как основной, так и альтернативных подпрограмм, если они были установлены.

Функция 19 (Query Alternate Event Handler) проверяет факт установки альтернативной подпрограммы, маска для поиска указывается в регистре сх. Если подпрограмма была установлена, то драйвер возвращает ее адрес в регистрах es:dx, в противном случае он помещает в регистрах код OFFFFh.

Ошибка в драйвере Mitsumi

Автор исследовал три драйвера мыши, разработанные фирмами Microsoft, Genius и Mitsumi. В последнем из них допущена трудно диагностируемая ошибка, она заключается в следующем. Если основная и альтернативная подпрограммы реагируют на одно и то же изменение состояния мыши, то драйвер отдает предпочтение основной и не вызывает альтернативную подпрограмму. В частности, если основная подпрограмма реагирует на любые изменения состояния мыши (код маски 7Fh), то альтернативные подпрограммы не будут вызваны драйвером ни при каких условиях. На этикетке установочной дискеты, прилагаемой к мыши, написано MITSUMI Mouse Driver Version 6.0.

Вызов подпрограммы драйвером

Если произошло событие, код которого указан в маске, то драйвер вызывает установленную подпрограмму. При входе в нее в регистрах bx, сх и dx находятся данные о состоянии кнопок и значениях координат, представленные в том виде, в котором они получаются после выполнения функции 3.

Три младших разряда регистра указывают состояние кнопок. Если разряд установлен, то соответствующая ему кнопка нажата, а если очищен, то не нажата. Разряды 0, 1, 2 соответствуют левой, правой и средней кнопкам.

Дополнительно в регистре ах находится код события, явившегося причиной вызова подпрограммы. В этом регистре может быть установлен только один из указанных в коде маски разрядов (см. описание функции ос). Например если подпрограмма вызывается при любом изменении состояния мыши (код маски 7Fh), то будет установлен один из 7 младших разрядов регистра ах.

Предположим, что оператор перемещает мышь при нажатой левой кнопке. В момент начала перемещения произойдут два вызова подпрограммы. В одном случае в регистре ах будет находиться код 1, а во втором 2. Какой из двух вызовов произойдет первым, зависит от того, что раньше сделал оператор — нажал левую кнопку или начал двигать мышь. В дальнейшем состояние левой кнопки не меняется до того момента, пока она не будет отпущена, поэтому при вызовах подпрограммы в регистре ах будет находиться код 1. При отпускании левой кнопки в регистре ах окажется код 4.

Если подпрограмма реагирует только на перемещение курсора (код маски 1), то состояние кнопок указывает код, находящийся в регистре .

В конце раздела говорилось о том, что драйвер поддерживает счетчики перемещений курсора (СП К) и мыши (СПМ), причем значения СПК он вычисляет по значениям СПМ. Обычно в прикладных задачах используется СП К, его значения возвращает функция Mouse з в регистрах сх и dx. В отличие от этой функции, при входе в прерывающую подпрограмму доступны оба типа счетчиков.

Значения СПК находятся в регистрах сх и dx, первый из них содержит текущее значение номера столбца, а второй — номера строки.

Значения СПМ находятся в регистрах si и di, первый из них содержит количество перемещений мыши по горизонтали, а второй — по вертикали. Оба счетчика очищаются при инициализации драйвера (функции 0 и 21) и при выполнении специальной функции ов. Текущие значения счетчиков могут быть отрицательными или положительными числами. Положительные значения соответствуют перемещениям мыши вправо и вниз, а отрицательные — влево и вверх. Обычно в прикладных задачах значения СПМ не используются.

Общие требования к подпрограммам

При входе в подпрограмму регистр ds содержит сегмент оперативной памяти, в котором расположен драйвер. Поэтому выполнение подпрограммы должно начинаться с записи в регистр ds значения сегмента данных задачи. Кроме того, драйвер использует регистр es для доступа к области данных BIOS, поэтому при входе в подпрограмму он может оказаться очищенным. Если подпрограмма использует регистр es при обращениях к видеопамяти, то в него надо записать код сегмента видеобуфера. Перед возвратом из подпрограммы в драйвер восстанавливать исходные значения регистров ds и es не требуется.

При разработке подпрограммы вы можете использовать регистры общего назначения по своему усмотрению, не заботясь о сохранении их исходных значений. После возврата в драйвер он восстановит содержимое тех регистров, которые нужны для продолжения работы.

Последней выполняемой командой подпрограммы должна быть retf. Если подпрограмма использует стек для своих нужд, то к моменту выполнения retf должно быть восстановлено исходное (на момент входа в подпрограмму) состояние стека. Последнее слово стека содержит сегмент оперативной памяти, в котором расположен драйвер, а предпоследнее — адрес возврата, относящийся к этому сегменту.

Замечание
Повторный вызов подпрограммы будет возможен только после того, как она выполнит команду retf и драйвер завершит обработку предыдущего события. Это упрощает структуру подпрограммы, но ограничивает время, в течение которого она может выполняться.

 
Назад Начало Вперед