Если программа запускается с клавиатуры с указанием каких-либо параметров (имен файлов, ключей, определяющих режим работы программы и проч.), то DOS, загрузив программу в память, помещает все символы, введенные после имени программы (так называемый хвост команды) в префикс программного сегмента программы, начиная с относительного адреса 80h. Хвост команды помещается в PSP во вполне определенном формате. В байт по адресу 80h DOS заносят число символов в хвосте команды (включая пробел, разделяющий на командной строке саму команду и ее хвост). Далее (начиная с байта по адресу 81h) следуют все символы, введенные с клавиатуры до нажатия клавиши <Enter>. Завершается хвост колом возврата каретки (13).
К данным секции инициализации добавилась строка с ожидаемым хвостом команды и байтовый флаг запроса на выгрузку.
Поскольку действия программы при её запуске зависят от того, введена ли команда запуска с параметром или нет, наличие хвоста в PSP анализируется в самом начале секции инициализации. При запуске программы типа СОМ все сегментные регистры указывают на начало PSP. Байт с длиной хвоста (возможно, нулевой) помещается в регистр CL и сравнивается с нулем. Если в нем 0, команда запуска была введена без параметров и инициализация программы продолжается обычным образом. Если хвост имеет ненулевую длину, начинается его анализ.
Обнулением регистра СН длина хвоста "расширяется" на весь регистр СХ, что нужно для организации цикла. Регистр DI настраивается на первый байт хвоста, а регистр SI – на начало поля tail с ожидаемой формой параметра. Регистр AL подготавливается для выполнения команды сканирования строки. Команда scasb сравнивает в цикле байты хвоста с содержимым AL (кодом пробела). Сравнение ведется до тех пор, пока не будет найден первый символ, отличный от пробела. Эта операция необходима из-за того, что оператор при вводе команды выгрузки может отделить параметр команды от самой команды любым числом пробелов, которые попадут в хвост команды в PSP и помешают анализировать введенный параметр.
Выход из цикла выполнения команды scasb осуществляется, когда команда проанализировала первый после пробела символ. После этого регистр DI указывает на второй символ параметра. Команда dec DI корректирует указатель DI, направляя его на первый значащий символ введенного параметра. Далее командой сравнения строк cmpsb осуществляется сравнение трех оставшихся символов хвоста. Если символы совпадают с параметром 'off', записанным в программе, устанавливается флаг запроса на выгрузку. Если результат сравнения оказался отрицательным, флаг запроса не устанавливается (и, следовательно, неправильный параметр просто не воспринимается). В любой случае осуществляется переход на продолжение программы, начинающей проверять, не установлена ли уже эта программа в памяти. Если программа еще не установлена, введенный параметр не имеет смысла. Инициализация осуществляется обычным образом: сохраняются и устанавливаются векторы и программа завершается с оставлением в памяти.
При наличии в памяти резидентной копии этой программы осуществляется переход на метку installed, где прежде всего проверяется, установлен ли флаг запроса на выгрузку. Если флаг сброшен, выводится сообщение о невозможности повторной загрузки и программа завершается с кодом возврата 1. Если флаг запроса установлен, выполняется выгрузка программы, которая заключается в вызове мультиплексного прерывания 2Fh с функцией F1h и подфункцией 01h. Резидентный обработчик этого прерывания, включенный в состав нашей резидентной программы, отработает эту подфункцию, восстановит векторы и освободит занятые программой блоки памяти. После возврата управления из обработчика в текущую программу будет выведено сообщение об успешной выгрузке и программа будет завершена функцией 4Ch с нулевым кодом возврата.
Составленная нами программа не избавлена от недостатков. Так, в ней анализируются всегда только 3 значащих символа хвоста. Таким образом, программа будет выгружена и при вводе команды (имя).com onset. Другой недостаток заключается в том, что результат сравнения записанного в программе хвоста с введенным с клавиатуры параметром будет положительным, только если с клавиатуры введены строчные буквы. Команда (имя) OFF не приведет к выгрузке программы. По-настоящему следовало включить в программу перед анализом хвоста преобразование символов параметра в прописные буквы.
2.4. Перехват прерываний
В архитектуре процессоров 80х86 предусмотрены особые случаи, когда процессор прекращает (прерывает) выполнение текущей программы и немедленно передает управление программе-обработчику, специально написанной для обработки подобной ситуации. Такие особые ситуации делятся на два тина: прерывания и исключения, в зависимости от того, вызвало ли эту ситуацию какое-нибудь внешнее устройство или выполняемая процессором команда. Исключения делятся далее на три типа: ошибки, ловушки и остановы, в зависимости от того, когда по отношению к вызвавшей их команде они происходят. Ошибки появляются перед выполнением команды, поэтому обработчик такого исключения получит в качестве адреса возврата адрес ошибочной команды (начиная с процессоров 80286). Ловушки происходят сразу после выполнения команды, так что обработчик получает в качестве адреса возврата адрес следующей команды. И наконец, остановы могут возникать в любой момент и вообще не предусматривать средств возврата управления в программу.
Команда INT (а также INTO и INT3) используется в программах как раз для того, чтобы вызывать обработчики прерываний (или исключений). Фактически они являются исключениями ловушки, поскольку адрес возврата, который передастся обработчику, указывает на следующую команду, но так как эти команды были введены до разделения особых ситуаций на прерывания и исключения, их практически всегда называют командами вызова прерываний. Ввиду того, что обработчики прерываний и исключений в DOS обычно не различают механизм вызова, с помощью команды INT можно передавать управление, как на обработчики прерываний, так и исключений. Как показано в главе 4, программные прерывания, то есть передача управления при помощи команды INT, являются основным средством вызова процедур DOS и BIOS, потому что в отличие от вызова через команду CALL здесь не нужно знать адреса вызываемой процедуры - достаточно только номера. С другой стороны интерфейса рассмотрим, как строится обработчик программного прерывания.
2.5. Обработчики прерываний
Когда в реальном режиме выполняется команда INT, управление передается по адресу, который считывается из специального массива, таблицы векторов прерываний, начинающегося в памяти по адресу 0000h:0000h. Каждый элемент такого массива представляет собой дальний адрес обработчика прерывания в формате сегмент:смещение или 4 нулевых байта, если обработчик не установлен. Команда INT помещает в стек регистр флагов и дальний адрес возврата, поэтому, чтобы завершить обработчик, надо выполнить команды popf и retf или одну команду iret, которая в реальном режиме полностью им аналогична.
После того как обработчик написан, следующий шаг - привязка его к выбранному номеру прерывания. Это можно сделать, прямо записав его адрес в таблицу векторов прерываний.
Хотя прямое изменение таблицы векторов прерываний и кажется достаточно удобным, все-таки это не лучший подход к установке обработчика прерывания, и пользоваться им следует только в исключительных случаях, например, внутри обработчиков прерываний. Для обычных программ DOS предоставляет две системные функции: 25h и 35h - установить и считать адрес обработчика прерывания, которые и рекомендуются к использованию в обычных условиях.
Обычно обработчики прерываний применяют с целью обработки прерывания от внешних устройств или с целью обслуживания запросов других программ.
2.6. Прерывания от внешних устройств
Прерывания от внешних устройств или аппаратные прерывания, - это то, что понимается под термином «прерывание». Внешние устройства (клавиатура, дисковод, таймер, звуковая карта и т. д.) подают сигнал, по которому процессор прерывает выполнение программы и передает управление на обработчик прерывания. Всего на персональных компьютерах используется 15 аппаратных прерываний, хотя теоретически возможности архитектуры позволяют довести их число до 64.
– IRQ1 (INT 9) - прерывание клавиатуры, вызывается при каждом нажатии и отпускании клавиши на клавиатуре. Стандартный обработчик этого прерывания выполняет довольно много функций, начиная с перезагрузки по Ctrl-Alt-Del и заканчивая помещением кода клавиши в буфер клавиатуры BIOS.
Самые полезные для программ аппаратные прерывания — прерывания системного таймера и клавиатуры. Так как стандартные обработчики этих прерываний выполняют множество функций, от которых зависит работа системы, их нельзя заменять полностью.
прерванной программе. Этот способ применяют, если нужно, чтобы сначала отработал новый обработчик, а потом он передал управление старому
Резидентные программы, перехватывающие аппаратные прерывания, обладают свойством выполнятся одновременно с какой-либо другой программой. Именно для этого и применяется механизм аппаратных прерываний - они позволяют процессору выполнять одну программу, в то время как отдельные программы следят за временем, считывают символы из клавиатуры и помещают их в буфер, получают и передают данные через последовательные и параллельные порты и даже обеспечивают многозадачность, переключая процессор между разными задачами по прерыванию системного таймера.