Системное программное обеспечение персональных ЭВМ

         

Программные коммуникации


15.5. Программные коммуникации

Под программными коммуникациями мы понимаем обращения к TSR-программе из других программ. Для чего может понадобиться такое обращение? Во-первых, если речь идет об ISR-программах, то их активизация может происходить только по программному обращению. Во-вторых, при инициализации TSR-программы необходимо проверять, нет ли уже копии этой программы в памяти. Следовательно, запускаемая программа должна обратиться к копии программы уже резидентной в памяти, а резидентная копия должна ответить на это обращение, подтвердив свое присутствие. Наконец, в-третьих, при запуске, например, нашей программы с параметром "/Q", она должна передать резидентной копии команду на самоуничтожение. Список соображений, по которым требуется обеспечение программных коммуникаций можно было бы продолжить.

Для программных коммуникаций можно использовать прерывания, закрепив для этих целей один из свободных векторов. В DOS 3.0 и далее для этих целей введено специальное прерывание 0x2F, именуемое мультиплексным. Каждый процесс (т.е. каждая TSR-программа) закрепляет за собой какую-либо функцию этого прерывания. Функции с номерами от 0 до 0xBF закреплены за DOS (известно, что функция 1 используется программой фоновой печати PRINT, 0xB7 - резидентной утилитой APPEND, 0x11 - внутренними вызовами DOS и т.д.), функции с номерами от 0xC0 до oxFF - для пользовательских программ. Поскольку одновременно несколько пользовательских резидентных программ могут находиться в памяти и использовать мультиплекское прерывание для своих коммуникаций, необходимо обеспечить разделение между ними функций, оставленных пользователям. По спецификациям прерывания 0x2F подфункция 0 (AL=0) любой функции должна обеспечивать индикацию занятости функции. При обращении к подфункции 0 любой функции прерывания 0x2F на выходе мы должны получать в регистре AL код 0 - если функция свободна и может быть захвачена пользовательской программой, или код 0xFF - если функция занята. Каждая программа, подключающаяся к прерыванию 0x2F должна обеспечить такое выполнение подфункции 0 для занимаемой ею функции, остальные подфункции можно назначать и использовать по своему выбору.



В нашем примере обработчиком прерывания 0x2F является функция new_2F. Номер функции прерывания 0x2F, которую занимает наша TSR-программа является переменной, значение которой устанавливается в процессе инициализации. Обработчик прерывания прежде всего анализирует содержимое регистра AH, сравнивая его с номером занятой нашей программой функции. Если они совпадают, то далее выбирается номер подфункции из регистра AL, и выполняются действия, определенные для данной подфункции. Для нашего обработчика определены 4 подфункции.


  • Подфункция 0. В соответствии с требованиями к обработке прерывания 0x2F наш обработчик по этой подфункции возвращает код 0xFF в регистре AL. Кроме того, чтобы показать, что данная функция занята именно нашей программой, в регистрах ES:BX он возвращает адрес символьной строки "TSR-программа 15_1 загружена".
  • Подфункция 0x10 предназначена для активизации TSR-программы из другой программы. По этой подфункции вызывается функция act_tsr.
  • Подфункция 0x20 - внутренний вызов TSR-программы, она вызывается из обработчика прерывания 0x13 для получения содержимого флагов микропроцессора. По этой подфункции содержимое флагов копируется из параметров new_2F в глобальную переменную cflag.
  • Подфункция 0x30 - команда на самоуничтожение TSR-программы, по ней вызывается функция self_kill.

Если функция, с которой вызвано прерывание 0x2F, нами не опознана, необходимо обратиться к прежнему обработчику этого прерывания. Обратите внимание на то, как оформлено это обращение. Трудности, возникающие при выполнении такого обращения, характерны для перехвата всех программных прерываний. Заключаются они в том, что программные прерывания получают входные параметры в регистрах, в регистрах же возвращают и выходные параметры. Поэтому перед обращением к прежнему обработчику необходимо позаботиться о восстановлении всех регистров, а при возврате из нашего обработчика - обеспечить передачу содержимого регистров, сформированного прежним обработчиком. Применительно к прерыванию 0x2F трудности усугубляются тем, что выполняемым через него внутренним вызовам DOS (функция 0x11) параметры передаются не только через регистры, но и через стек, так что надо позаботиться о том, чтобы и содержимое стека при вызове старого обработчика было идентично тому, которое имелось при выдаче команды INT 2Fh.При программировании на языка Ассемблера это легко обеспечивается передачей управления на старый обработчик командой JMP, а не CALL. Здесь же нам приходится производить некоторые манипуляции со стеком, иллюстрируемые Рисунок 15.1.


Содержание раздела