
Dos7book
.pdf
Глава 8: Вызовы обработчиков прерываний
Примечание 2: блок данных в буфере начинается со слова, означающего его длину, а данные из DPB следуют начиная со смещения DI+02.
Примечание 3: в скопированной таблице DPB место адреса заголовка драйвера (слово со смещением 13h) заполнено значением FFFFh.
Примечание 4: при вызове обработчик прерывания INT 21\AX=7302h старается обновить данные DPB путем считывания блока BPB с диска. Если попытка считывания кончается неудачно, то происходит вызов обработчика критических ошибок – прерывания INT 24.
8.02-80 INT 21\AX=7303h – таблица свободного дискового пространства
Обработчик прерывания INT 21\AX=7303h выдает сведения о наличии свободного пространства на дисках с файловыми системами FAT-12, FAT-16 и FAT-32. Сведения выдаются в виде блока данных A.13-7, копируемого в подготовленный буфер. В отличие от величин, возвращаемых функцией INT 21\AH=36h (8.02-30), величины в блоке данных A.13-7 не ограничены значением 2048 Мбайт.
При вызове: |
|
AX |
= 7303h |
CX |
– длина буфера для данных, не менее 34h байт |
DS:DX – указатель на строку, определяющую диск (примечание 2) ES:DI – указатель на буфер для данных; при вызове в буфере слово со
смещением 02h должно быть 0000h.
При неудачном завершении флаг CF установлен, в AX – код завершения (A.06-1). Если флаг CF сброшен, то в буфере ES:DI – блок данных A.13-7.
Примечание 1: в отличие от подобной функции INT 21\AH=36h (8.02-30), функция INT 21\AH=7303h недоступна в предыдущих версиях DOS и нуждается в том, чтобы система BIOS компьютера поддерживала расширенный набор функций прерывания INT 13 (8.01-55).
Примечание 2: строка определяет запрашиваемый диск в той же форме, в которой он определен в таблице CDS (A.03-3), например, C:\ для локальных дисков и \\SERVER\Share для дисков, доступных по сети. Строка должна кончаться байтом 00h.
8.02-81 INT 21\AX=7305h – расширенные операции считывания и записи
Обработчик прерывания INT 21\AX=7305h представляет 5 операций считывания и записи с адресацией по номерам секторов, отсчитываемым отдельно от начала каждого логического диска. Эти операции подобны функциям INT 25 и
– 429 –

Глава 8: Вызовы обработчиков прерываний
INT 26 (8.02-85), однако применимы не только к дискам с файловыми системами FAT-12 и FAT-16, но также к дискам с файловой системой FAT-32.
При вызове: |
|
|
AX |
= 7305h |
|
DL |
– номер логического диска (примечание 1 к 8.02-17) |
|
DS:BX – указатель на пакет дисковой адресации (примечание 2). |
||
SI |
– операция: |
|
|
= 0000h – считывание |
|
|
= 0001h – запись произвольных данных |
|
|
= 2001h |
– запись данных таблицы FAT |
|
= 4001h |
– запись данных каталога |
|
= 6001h |
– запись данных в файл |
При неудачном завершении флаг CF установлен, в AX – код завершения (A.06-1). Если флаг CF сброшен, то операция завершена успешно.
Примечание 1: в отличие от подобных функций INT 25 и INT 26 (8.02-85), функция INT 21\AH=7305h недоступна в предыдущих версиях DOS и нуждается в том, чтобы система BIOS компьютера поддерживала расширенный набор функций прерывания INT 13 (8.01-55).
Примечание 2: пакет дисковой адресации имеет длину 10 байт и содержит:
00h – двойное слово: номер сектора, с которого надо начать; 04h – слово: сколько секторов надо считать или записать;
06h – двойное слово: адрес буфера с данными или для данных.
8.02-82 INT 22 – адрес завершающей передачи управления
Соответствующий прерыванию INT 22 адрес перехода указывает не на обработчика, а на точку возврата в родительский процесс, то есть туда, куда должно быть передано управление после окончания работы текущей программы. Обычно адрес INT 22 указывает на команду, стоящую вслед за вызовом функции INT 21\AH=4Bh (8.02-53), которая запустила на исполнение текущую программу.
Прерывание INT 22 не вызывают непосредственно, потому что родительский
процесс не может правильно возобновиться без восстановления состояния стека и многого другого, в том числе адресов для прерываний INT 22 – INT 24 в таблице прерываний. Все необходимые подготовительные операции входят в процедуру завершения работы текущей программы, выполняемую обработчиками прерываний
INT 20 и INT 21\AH=4Ch (8.02-55). Они считывают адрес INT 22 из таблицы прерываний, копируют на его место адрес INT 22 для родительского процесса, хранимый в двойном слове со смещением 0Ah в префиксе сегмента текущей программы (PSP, A.07-1), а затем выполняют дальний переход по адресу, заранее считанному из таблицы прерываний.
– 430 –

Глава 8: Вызовы обработчиков прерываний
8.02-83 INT 23 – останов исполнения текущей программы
Распознав нажатия клавишных комбинаций Ctrl-C или Ctrl-Break, обработчик прерывания INT 09 вызывает обработчика прерывания INT 1B (8.01-95), который взводит в состояние логической единицы флаг Ctrl-Break по адресу 0040:0071h в области данных BIOS (A.02-3). Состояние этого флага проверяют обработчики прерываний, установленные MS-DOS, когда их вызывает исполняемая программа. Обнаружив взведенное состояние флага, они вызывают обработчика прерывания INT 23. Именно он останавливает исполнение текущей программы.
Код обработчика прерывания INT 23 написан в расчете на то, что вызывающим процессом для него является функция DOS. Поэтому прямой вызов INT 23 из пользовательских программ не допускается, возможен только косвенный вызов через INT 1B (8.01-95).
Дальнейшее развитие событий частично зависит от обстоятельств вызова, но в большинстве ситуаций обработчик прерывания INT 23 ставит пользователя перед выбором: продолжить или завершить исполнение приостановленной программы. Возможные ответные действия пользователя описаны в разделе 1.03. Если будет избран вариант "завершить", то обработчик прерывания INT 23 закроет файлы, открытые приостановленной программой, высвободит занимаемую ей память, задаст нулевое значение возвращаемого уровня ошибки, установит флаг CF в состояние CY, и затем передаст управление родительскому процессу – тому, который вызвал на исполнение закрываемую программу. Если пользователем будет избран вариант "продолжить", то произойдет возврат к исполнению кода того обработчика прерывания, из которого произошел вызов INT 23, причем состояния регистров и флагов будут сохранены. Завершив свою миссию, этот обработчик возвратит управление вызывавшей его текущей программе.
8.02-84 INT 24 – обработчик критических ошибок
Когда система BIOS или порты неадекватно реагируют на обращения функций DOS к аппаратуре компьютера, тогда эти функции DOS вызывают INT 24 – обработчика критических ошибок. Обработчик критических ошибок анализирует переданные ему сведения об ошибке, но не очень надеется на себя; обычно он адресует пользователю свой знаменитый вопрос "Abort, Retry, Fail?", а потом передает решение пользователя для исполнения той функции DOS, которая вызвала
INT 24.
Код обработчика прерывания INT 24 написан в расчете на то, что вызывающим процессом для него является функция DOS. Поэтому прямой вызов INT 24 из пользовательских программ не допускается.
– 431 –

Глава 8: Вызовы обработчиков прерываний
При возврате состояния регистров (кроме AL) восстанавливаются по сохраненным в стеке значениям, а в регистре AL возвращается код действия:
AL = 00h – вернуться в вызывающую программу с ошибкой (fail);
=01h – повторить исполнение запрошенной операции (retry);
=02h – прекратить исполнение вызывающей программы (abort);
=03h – констатировать системный отказ, остановить процессор.
Примечание 1: автоматическая выдача ответа FAIL и безостановочное
продолжение исполнения обеспечиваются предварительной установкой флага в ячейке со смещением 2Ah в области текущих данных DOS (A.01-3). Этим пользуется, в частности, интерпретатор COMMAND.COM, когда принимает недокументированный параметр /F (6.04).
8.02-85 Считывание (INT 25) и запись (INT 26) с прямым доступом к диску
Обработчики прерываний INT 25 и INT 26 осуществляют доступ только в пределах логических дисков с файловыми системами FAT-12 и FAT-16, причем с адресацией по номерам секторов в обход файловой системы. На каждом логическом диске счет секторов начинается заново с номера 00000000h. Адрес
буфера и конкретные номера секторов передаются в составе пакета дисковой адресации, показанного в примечании 2 к 8.02-81.
При вызове: |
|
AL |
– номер логического диска (примечание 1 к 8.02-10) |
CX |
= FFFFh (примечание 3) |
DS:BX – пакет дисковой адресации (примечание 2 к 8.02-81). При возврате состояния регистров BX, CX, DX, DI, SI не сохраняются.
При неудачном завершении флаг CF установлен, в AL – код завершения (A.06-1), в
AH – статус ошибки, показанный в таблице A.06-5. Если флаг CF сброшен, то миссия завершена успешно.
Примечание 1: после вызова INT 25 и INT 26 в вершине стека остается слово, отображающее исходное состояние флагов. Состояние стека должно быть восстановлено вызывающей программой. Нужно либо вытолкнуть это слово из стека, либо записать прежнее значение в регистр SP.
Примечание 2: обработчикам прерываний INT 25 и INT 26 доступны те логические диски, для которых драйвер способен обеспечить 32-разрядный обмен, что отмечается установлением бита 1 в слове атрибутов в заголовке драйвера (A.05-2).
Примечание 3: вызовы INT 25 и INT 26 со значением CX < FFFFh допустимы только по отношению к логическим дискам емкостью менее 32
– 432 –

Глава 8: Вызовы обработчиков прерываний
Мбайт без кластерной структуры, которые маркируются идентификатором 04h из таблицы A.13-6. При обращении к таким дискам пакет дисковой адресации не употребляется, в регистры записывается следующее:
CX – число секторов DX – начальный сектор
DS:BX – указатель на буфер с данными или для данных. Примечание 4: для обращений к дискам с файловой системой FAT-32 обработчики
прерываний INT 25 и INT 26 непригодны, вместо них следует использовать INT 21\AX=7305h (8.02-81).
8.02-86 |
INT 27 – завершение исполнения с оставлением TSR-модуля |
|
При вызове: |
|
|
|
CS |
– сегментный адрес PSP |
|
DX |
– размер резидентного модуля в байтах, от 60h до FFF0h байт, |
|
|
отсчитываемый от начала PSP. |
Примечание 1: вызов INT 27h высвобождает всю занятую программой память, за исключением резидентного модуля, восстанавливает указатели в таблице прерываний по данным из PSP, но не закрывает открытые файлы: это должна сделать сама программа до вызова INT 27h.
Примечание 2: обработчик прерывания INT 21\AH=31h (8.02-23) делает то же самое, но сверх того позволяет оставить ненулевые значения кода уровня ошибки (errorlevel) и не ограничивает размер резидентного модуля величиной 64 кбайт.
8.02-87 INT 28 – механизм фонового исполнения программ
DOS вызывает INT 28 в темпе тактов 18 раз в секунду в те интервалы времени, когда исполняемые операции ввода (INT 21\AH=01h-0Ch) ожидают ввода знаков с клавиатуры. В этих интервалах ожидания DOS фактически мается без дела. Устанавливаемый по умолчанию обработчик прерывания INT 28 представляет собой одну команду IRET (7.03-30), которая просто возвращает управление вызывающей программе. Перехват вызовов INT 28 позволяет активизировать другую программу, предназначенную для исполнения в фоновом режиме, пока основная программа ожидает ввода знаков пользователем. Перехватывающий обработчик вызовов INT 28 получает в регистрах SS:SP адрес, указывающий на вершину стека DOS, а при возврате должен восстановить состояния всех регистров.
Примечание 1: программы, активизируемые посредством INT 28, должны прежде всего проверять состояние флага InDOS (01h в таблице A.01-3),
причем адрес этого флага должен быть найден заранее с помощью
– 433 –

Глава 8: Вызовы обработчиков прерываний
INT 21\AH=34h (8.02-28) и сохранен с момента инициализации программы. Флаг InDOS в момент вызова INT 28 нормально имеет значение 01h; если значение больше 01h, то в фоновой программе нельзя вызывать на исполнение никакие функции DOS.
Примечание 2: программы, предназначенные для фонового исполнения путем перехвата INT 28 при значении 01h флага InDOS, могут пользоваться функциями DOS, однако не допускаются обращения к функциям INT 21\AH=01h-0Ch, а также обращения к номерным ссылкам устройства CON (обычно это ссылки 0000h – 0002h).
8.02-88 INT 29 – неперенаправляемое отображение знака на экране
К вызову INT 29 прибегают тогда, когда нужно вывести сообщение на экран дисплея, несмотря на то, что канал STDOUT может быть перенаправлен и что в качестве средства ввода-вывода может быть заявлено какое-либо иное устройство вместо принимаемого по умолчанию устройства CON (консоли).
При вызове:
AL – код ASCII знака, который надо отобразить на экране При возврате содержимое регистра BX может быть утрачено.
Примечание 1: обработчик прерывания INT 29 осуществляет индикацию знака на экране посредством вызова INT 10\AH=0Eh (8.01-21).
Примечание 2: о поддержке INT 29 свидетельствует установление бита 4 в слове атрибутов драйвера устройства CON (A.05-2).
Примечание 3: неперенаправляемое отображение строки знаков можно осуществить также через номерную ссылку 0002h на канал STDERR
посредством INT 21\AH=40h (8.02-36). В отличие от INT 29, такой вывод знаков всегда поддерживается драйвером устройства CON.
8.02-89 INT 2E – передача команды командному интерпретатору
Посредством вызова INT 2E программа передает командную строку на исполнение командному интерпретатору COMMAND.COM, причем новый резидентный модуль командного интерпретатора не загружается. Команда передается тому самому резидентному модулю, который запустил на исполнение вызывающую программу.
При вызове:
DS:SI – адрес командной строки в том формате, в каком она вписывается в PSP (A.07-1) начиная со смещения 80h. В первом байте строки должна быть указана ее длина. Конец строки отмечается байтом 0Dh, который не входит в счет длины строки.
– 434 –

Глава 8: Вызовы обработчиков прерываний
При возврате:
AX – код завершения (A.06-1);
состояния всех других регистров, кроме CS:IP, не сохраняются.
Примечание 1: перед вызовом INT 2E вызывающая программа должна убедиться в том, что имеется достаточно свободной памяти для размещения подгружаемых модулей командного интерпретатора.
Примечание 2: вызванный прерыванием INT 2E командный интерпретатор работает со своими исходными переменными окружения, которые
могут отличаться от переменных окружения вызывающей программы. Все изменения переменных окружения, которые могут произойти в ходе исполнения, не будут доступны вызывающей программе.
Примечание 3: не следует вызывать INT 2E из программ, которые запускаются из batch-файлов.
8.03Обработчики от драйверов и резидентных программ
Входе загрузки любого резидентного обработчика прерывания должна быть обеспечена возможность его вызова посредством адреса, занесенного в таблицу прерываний. Однако прежде чем любая программа сможет воспользоваться этим адресом, она должна убедиться, что в конкретной ячейке таблицы прерываний записан именно адрес вызова. Такой вопрос не стоит по отношению к модулям, поставляемым системами BIOS и DOS: их адреса – заведомо на своих местах. Но драйвер может быть не загружен, и тогда обращение к соответствующей ячейке, не содержащей адреса, почти наверняка приведет к "зависанию" компьютера.
Сначала, когда драйверов было не слишком много, каждому из них выделяли свою ячейку в таблице прерываний, и тогда определять факт загрузки драйвера
можно было по наличию сигнатуры в определенной позиции относительно записанного в ячейку сегментного адреса. Именно так определяют, например, факт загрузки драйвера EMM386.EXE (примечание 1 к 8.03-62), "предки" которого известны с 1983 года.
Потом драйверов становилось все больше, и на ограниченном пространстве таблицы прерываний стали возникать конфликты. Помимо того, надо было устранить опасность "зависания" компьютера при обращении к отсутствующим модулям. Для решения обеих этих проблем была предложена идея обращения ко
всем резидентным модулям драйверов посредством мультиплексного прерывания INT 2F. Предполагается, что каждый участвующий драйвер перехватывает вызовы INT 2F, образуя тем самым звено в цепи ссылок (подробнее – в A.07-5). Вызов передается по цепи ссылок от одного обработчика к другому, и каждый из них анализирует идентификатор, записанный в регистр AH. Если обработчик не сочтет
– 435 –

Глава 8: Вызовы обработчиков прерываний
идентификатор "своим", то вызов в неизменном виде продолжит путешествие по цепи ссылок. Последней будет ссылка на команду IRET, которую первоначально загрузила DOS. Команда IRET возвратит управление вызывающей программе, не изменяя состояния регистров. Любое изменение их первоначального состояния будет означать, что один из обработчиков посчитал идентификатор "своим". Следовательно, запрошенный резидентный модуль уже загружен.
Разумеется, мультиплексное прерывание можно использовать не только для опознания. Оно дает возможность обращаться к основным функциям резидентных модулей без риска зависания компьютера, если требуемый модуль не загружен.
Однако прослеживание цепи ссылок при каждом вызове существенно замедляет работу программ. Во избежание задержек многие драйверы передают через INT 2F прямой адрес вызова своих специфических функций, чтобы далее программы могли пользоваться этими функциями, не обращаясь к мультиплексному прерыванию. Именно так строит свое взаимодействие с программами, например,
драйвер Himem.sys (8.03-22, 8.03-23).
Практика пользования прерыванием INT 2F получила распространение, но не могла предотвратить конфликты из-за несогласованного назначения одинаковых
фиксированных идентификационных кодов многим разным драйверам и резидентным модулям. Во избежание таких конфликтов было предложено
разрешить любому резидентному модулю присваивать себе первый попавшийся идентификационный код, который будет найден незанятым в момент загрузки. Эта идея реализована мультиплексным прерыванием INT 2D (подробнее – в A.07-6), которое избавляет от конфликтов программы, разрабатываемые в настоящее время.
Вместе с тем старые драйверы с давно известными идентификационными кодами продолжают использовать прерывание INT 2F. Более того, отдельные резидентные модули, которые в прежних версиях DOS загружались с помощью драйверов, теперь вошли в состав ядра DOS, но ради сохранения совместимости по-прежнему вызываются посредством INT 2F. По этой причине проверка факта загрузки модулей с идентификационными кодами AH = 05h, 08h и 12h не имеет смысла – они фактически представляют функции DOS. Чтобы не потерять удобство порядкового поиска материалов, вызовы этих и нескольких других функций описаны ниже в разделе 8.03 наряду с вызовами функций загружаемых драйверов.
8.03-01 |
INT 2F\AX=0501h – преобразование кода завершения в сообщение |
||
При вызове: |
|
|
|
|
AX |
= 0501h |
|
|
BX |
– преобразуемый код завершения (A.06-1) |
|
При возврате: если флаг CF сброшен, то |
|||
|
AL |
= 00h |
– сообщение нужно дополнить буквой диска |
|
|
= 01h |
– сообщение готово к посылке на экран дисплея |
– 436 –

Глава 8: Вызовы обработчиков прерываний
ES:DI – указатель на строку сообщения с байтом 00h в конце. При неудаче флаг CF установлен: значит, для данного кода нет сообщения. При любом исходе состояния флагов и регистров AX, DI, ES не сохраняются.
8.03-02 INT 2F\AX=0801h – добавление логического диска
Обработчик прерывания INT 2F\AX=0801h добавляет подготовленную таблицу к последовательности таблиц DDT (Disk Data Tables, A.03-2), и исправляет соответствующим образом ссылки в других таблицах DDT, относящихся к тому же физическому дисководу. С этого момента добавленный логический диск становится открыт для доступа с помощью дисковых драйверов, входящих в состав ядра DOS.
При вызове:
AX = 0801h
DS:DI – указатель на подготовленную таблицу DDT (A.03-2) При возврате состояния регистров AX, BX, SI, ES не сохраняются.
Примечание 1: не следует применять INT 2F\AX=0801h по отношению к дискам с устанавливаемой файловой системой (IFS, 5.08-01), к сетевым и другим дискам, если драйверы из состава ядра DOS не способны эти диски обслужить.
Примечание 2: образец таблицы DDT можно получить с помощью
INT 2F\AX=0803h.
8.03-03 INT 2F\AX=0802h – отсылка запроса дисковому драйверу
Обработчик прерывания INT 2F\AX=0802h посылает запросы к драйверам логических дисков, входящих в состав ядра DOS. Запросы должны относиться к дискам, обслуживаемым этими драйверами и представленным в таблицах DDT (Disk Data Tables, A.03-2). Номер запрашиваемого диска вместе с кодом операции (A.05-3) указываются в блоке данных запроса (A.05-4).
При вызове:
AX = 0802h
ES:BX – указатель на блок данных запроса (A.05-4)
При возврате результаты отображаются в блоке данных запроса в соответствии с запрошенной операцией (A.05-3 – A.05-7).
Примечание 1: после вызова INT 2F\AX=0802h в вершине стека остается слово, отображающее исходное состояние флагов. Состояние стека должно быть восстановлено вызывающей программой. Нужно либо вытолкнуть это слово из стека, либо записать прежнее значение в регистр SP.
– 437 –

Глава 8: Вызовы обработчиков прерываний
Примечание 2: неудачное завершение отображается кодами в байтах со смещением 03h и 04h в блоке данных запроса (A.05-4), но в любом случае вызов обработчика критических ошибок (INT 24) не производится.
8.03-04 INT 2F\AX=0803h – определение адреса первой таблицы DDT
При вызове:
AX = 0803h
При возврате:
DS:DI – указатель на начало первой таблицы DDT (A.03-2)
Примечание 1: последовательность таблиц DDT несложно проследить, поскольку каждая таблица начинается с 4-байтового указателя на следующую таблицу DDT (A.03-2).
8.03-05 INT 2F\AX=1202h – указатель на адрес обработчика прерывания
При вызове:
AX = 1202h
Номер запрашиваемого прерывания – в верхнем регистре стека При возврате:
ES:BX – указатель на адрес обработчика прерывания;
значение в регистре AX утрачивается; состояние стека не изменяется.
Примечание 1: при работе в реальном режиме эта функция просто умножает номер прерывания на 4.
8.03-06 |
INT 2F\AX=1212h – определение длины строки |
|
При вызове: |
|
|
|
AX |
= 1212h |
|
ES:DI – указатель на строку, длину которой надо определить. Строка |
|
При возврате: |
должна заканчиваться байтом 00h. |
|
|
||
|
CX |
– длина строки, включая последний байт 00h. |
Примечание 1: обработчик прерывания INT 2F\AX=1225h делает то же самое, но только принимает указатель на строку из регистров DS:SI.
8.03-07 INT 2F\AX=1213h – перевод строчной буквы в заглавную
При вызове:
AX = 1213h
Код ASCII строчной буквы – в верхнем регистре стека.
– 438 –