Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Dos7book

.pdf
Скачиваний:
97
Добавлен:
09.02.2015
Размер:
5 Мб
Скачать
☆

Приложение А.06:

Коды ошибок

Примечание 1: если в спецификации указано, что код ошибки возвращается в регистре AX, то его старший байт – нулевой (AH = 00h).

Примечание 2: при коде ошибки 22h в регистрах ES:DI возвращается указатель на идентификатор носителя, в котором:

со смещения 00h – 12 байтов: метка тома диска с 00h в конце, со смещения 0Ch – 4 байта: серийный номер диска (двоичный).

Примечание 3: драйвер Himem.sys возвращает код ошибки в регистре BL. Примечание 4: коды завершения функций DOS хранятся в области SDA (A.01-3,

смещение 04h). Коды завершения функций BIOS записываются в области данных BIOS (A.01-1, обычно смещение 74h).

A.06-2 Значения класса ошибки, возвращаемые MS-DOS

Приведенная ниже таблица интерпретирует значения класса ошибки, возвращаемые обработчиком прерывания INT 21\AH=59h (8.02-65) в регистре BH, а также записываемые в области текущих данных (SDA, A.01-3) в ячейку со смещением 07h.

Код

Значение

01h

Не хватает ресурсов компьютера

02h

Временная ситуация

03h

Проблемы прав доступа

04h

Внутренние проблемы программного обеспечения

05h

Сбои и отказы оборудования

06h

Системные ошибки конфигурирования

07h

Ошибки прикладных программ

08h

Неудачи поиска объектов

09h

Несовместимость форматов

0Ah

Отказы, вызванные закрытием объектов

0Bh

Ошибки, вызванные носителями записи

0Ch

Дублирование существующих имен

0Dh

Ошибки из-за невыясненных причин.

A.06-3 Коды предлагаемых действий

Приведенная ниже таблица интерпретирует коды предлагаемых действий, возвращаемые обработчиком прерывания INT 21\AH=59h (8.02-65) в регистре BL, а также записываемые в области текущих данных (SDA, A.01-3) в ячейку со смещением 06h.

– 629 –

Приложение А.06:

Коды ошибок

 

Код

 

Рекомендация

 

01h

 

Повторить попытку

 

02h

 

Повторить попытку через некоторое время

 

03h

 

Предложить пользователю ввести данные повторно

 

04h

 

Закрыть файлы, удалить временные файлы, выйти из программы

 

05h

 

Выйти из программы немедленно

 

06h

 

Игнорировать ошибку

 

07h

 

Повторить попытку после вмешательства пользователя

A.06-4

Коды вероятного места возникновения ошибки

Приведенная ниже таблица интерпретирует коды вероятного места возникновения ошибки, возвращаемые обработчиком прерывания INT 21\AH=59h (8.02-65) в регистре CH, а также записываемые в области текущих данных (SDA, A.01-3) в ячейку со смещением 03h.

 

Код

 

Вероятная локализация

 

01h

 

Источник ошибки не определен

 

02h

 

Дисковые или ленточные накопители

 

03h

 

Локальные сети

 

04h

 

Устройства, подключенные к последовательному порту

 

05h

 

Память компьютера

A.06-5

Коды статуса ошибок ввода-вывода

Данная таблица интерпретирует коды статуса ошибок, возвращаемые в регистре AH обработчиками прерываний INT 25 и INT 26 (8.02-85).

Код

Значение

01h

Неверная команда

02h

Ошибочная адресная метка

03h

Диск защищен от записи (только после INT 26)

04h

Запрошенный сектор не найден

08h

Ошибка DMA (прямого доступа к памяти)

10h

Ошибка в данных, выявляемая с помощью кода CRC

20h

Отказ контроллера

40h

Ошибка при исполнении поиска

80h

Устройство не отвечает, время ожидания истекло

– 630 –

Приложение А.07: Структуры данных для исполнения программ

A.07 Структуры данных для исполнения программ

A.07-1 Префикс сегмента программы

Когда программа загружается для исполнения в выделенный сегмент памяти, ее исполняемый код размещается начиная со смещения 100h и дальше. Предшествующая часть сегмента (смещения 00h – FFh) известна как область PSP (Program Segment Prefix), или префикс сегмента программы. Область PSP заполняется важными служебными данными, которые используются функциями DOS и могут быть использованы самой исполняемой программой.

С помощью отладчика DEBUG.EXE проще всего "подглядеть" ту область PSP, которую для него формирует командный интерпретатор COMMAND.COM. Процедура вывода части этой области PSP на экран показана на рис. 11. Оставшаяся не показанной часть этой области PSP заполнена нулями.

Рис. 11

Роль отлаживаемой программы на рис. 11 играет файл CJPEG.EXE. Параметры "-baseline" и "VC01.BMP" передаются отлаживаемой программе, чтобы показать пример заполнения первого и второго блоков FCB, начинающихся со смещений 5Ch и 6Ch соответственно. Расположение упомянутых и некоторых других полей данных в области PSP пояснено в приведенной ниже таблице.

– 631 –

Приложение А.07: Структуры данных для исполнения программ

Смещение

Длина

Содержание

00h

2

Команда INT 20 (для совместимости с CP/M)

02h

2

1-й занятый сегмент после сегмента данного PSP

06h

2

Размер кода в сегменте (для .COM-файлов)

0Ah

4

Запомненный адрес возврата для INT 22

0Eh

4

Запомненный адрес обработчика INT 23

12h

4

Запомненный адрес обработчика INT 24

16h

2

Сегмент родительского PSP (примечания 1 и 2)

18h

20

Таблица Job File Table (JFT, примечание 3)

2Ch

2

Сегмент области окружения данной программы

2Eh

4

SS:SP перед последним вызовом INT 21

32h

2

Число ссылок в таблице JFT (по умолчанию 20)

34h

4

Указатель на таблицу JFT (обычно PSP:0018h)

3Ch

1

= 00h (= 01h – для иероглифических клавиатур)

40h

2

Номер версии DOS для INT 21\AH=30h

50h

2

Вызова обработчика прерывания INT 21

5Ch

16

Первый блок FCB (примечание 4)

6Ch

16

Второй блок FCB (примечание 4)

80h

1

Длина командной строки (примечания 5 и 6)

81h

127

Копия командной строки и область DTA

Примечание 1: если вместо сегментного адреса родительского PSP в слове со смещением 16h записан собственный сегментный адрес PSP данной программы, то эта программа считается не имеющей "прародителя". Так отмечаются постоянно загруженные программы, например, командный интерпретатор. Эти программы невозможно закрыть вызовом прерывания INT 20 или INT 21\AH=4Ch.

Примечание 2: при защищенном режиме работы компьютера в PSP могут быть внесены дополнительные данные, перезаписывающие некоторые поля PSP, в том числе сегментный адрес родительского PSP в слове со смещением 16h. Поэтому при прослеживании цепи ссылок на родительские PSP необходимо убедиться в том, что адрес действительно указывает на PSP, например, посредством проверки характерных сигнатур: CD20h (INT 20) начиная со смещения 00h или CD21h (INT 21) начиная со смещения 50h.

Примечание 3: в момент запуска программы на исполнение таблица JFT (смещение 18h в PSP) содержит однобайтовые номера блоков описания, входящих в таблицу SFT (A.01-4). Эти номера соответствуют блокам описания тех "открытых" объектов, которые унаследованы от родительского процесса. Номерами 80h – FEh отмечаются блоки описания файлов, доступ к которым осуществляется через сеть.

– 632 –

Приложение А.07: Структуры данных для исполнения программ

Оставшееся свободное пространство JFT заполняется байтами FFh. Начальный размер JFT – 20 байтов – ограничивает число объектов, которые можно держать открытыми одновременно. Это ограничение можно преодолеть путем формирования таблицы JFT большего размера за пределами PSP (8.02-76) и помещения указателя на нее в PSP начиная со смещения 34h. Но надо иметь ввиду, что дочерние процессы все равно не смогут наследовать более 20 открытых объектов.

Примечание 4: поля, начинающиеся со смещений 5Ch и 6Ch, предназначены для неоткрытых блоков FCB (A.09-5). Туда записываются первый и второй параметры командной строки, предварительно подвергнутые

"разбору" с помощью INT 21\AX=2901h (8.02-19), при этом счет параметров включает те, которые "разбору" не подлежат.

Примечание 5: область 81h – FFh заполняется копией командной строки запуска текущей программы. Заполненная часть заканчивается байтом 0Dh. Длина заполненной части записывается в байт со смещением 80h. Если длина равна 7Fh, и в байт со смещением FFh занесено значение 0Dh, то, значит, реальная длина командной строки превосходит 126 байтов, и тогда неурезанную версию командной строки следует искать в переменной окружения CMDLINE.

Примечание 6: область 80h – FFh также по умолчанию используется в качестве DTA (Data Transfer Area) при операциях поиска обработчиками прерываний INT 21\AH=11h,12h,4Eh,4Fh. Если записанная там же копия командной строки должна быть сохранена, то надо сменить адрес DTA с помощью INT 21\AH=1Ah (8.02-16).

A.07-2 Блок параметров загрузки программы

В приведенной ниже таблице показана структура блока параметров, используемого обработчиками прерываний INT 21\AX=4B00h и INT 21\AX=4B01h (8.02-53) при загрузке программы в память с целью ее последующего исполнения.

Смещение

Длина

Содержание

00h

2

Сегмент окружения дочернего процесса

02h

4

Указатель на командную строку (примечание 2)

06h

4

Адрес данных для FCB 5Ch (примечание 3)

0Ah

4

Адрес данных для FCB 6Ch (примечание 3)

0Eh

4

При возврате: адрес вершины стека SS:SP

12h

4

При возврате: адрес вызова CS:IP (примечание 4)

Примечание 1: в сегмент окружения дочернего процесса будет скопировано окружение вызывающего (родительского) процесса. Если дочернему

– 633 –

Приложение А.07: Структуры данных для исполнения программ

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

Примечание 2: здесь следует указать все, что должно быть записано в PSP дочернего процесса, начиная с адреса 80h (примечание 5 к A.07-1). Строка должна начинаться с байта, указывающего ее длину, и кончаться байтом 0Dh.

Примечание 3: эта строка данных будет скопирована в соответствующий блок FCB (примечание 4 к A.07-1) в PSP дочернего процесса. Структура строки показана в колонке "N" таблицы A.09-5, заполнению подлежат первые 12 байт, потом следуют 4 байта 00h. Если данный блок FCB не должен быть заполнен, то за первым байтом 00h должны следовать 11 байтов 20h.

Примечание 4: указатели в ячейках со смещениями 0Eh и 12h относятся только к функции INT 21\AX=4B01h, которая загружает программу, но не инициирует ее исполнение. Чтобы инициировать ее исполнение позже, функция INT 21\AX=4B01h возвращает адрес вызова загруженной программы и указатель на вершину ее стека.

A.07-3 Дескриптор состояния исполнения

Приведенная ниже таблица показывает структуру данных в дескрипторе, используемом при вызове прерывания INT 21\AX=4B05h (8.02-54).

Смещение

Длина

Содержание

00h

2

= 0000h (резервировано)

02h

2

Флаги: бит 0: исполнять как программу *.EXE

 

 

бит 1: загружаемый код – это оверлей

04h

4

Указатель на имя программы с байтом 00h в конце

08h

2

Сегментный адрес PSP загружаемой программы

0Ah

4

Адрес вызова загружаемой программы (CS:IP)

0Eh

4

Размер загружаемой программы, включая ее PSP

A.07-4 Блок параметров для вызова серверной функции

Поскольку серверная функция INT 21\AX=5D00h (8.02-68) исполняет каждый вызов прерывания INT 21 как отдельный процесс, постольку блок параметров, структура которого показана ниже, задает все исходные состояния регистров для исполнения той функции прерывания INT 21, которую предстоит вызвать. Перед

вызовом этой функции значения из блока параметров будут скопированы в регистры автоматически.

– 634 –

Приложение А.07: Структуры данных для исполнения программ

Смещение

Длина

Содержание

00h

2

Содержимое регистра AX

02h

2

Содержимое регистра BX

04h

2

Содержимое регистра CX

06h

2

Содержимое регистра DX

08h

2

Содержимое регистра SI

0Ah

2

Содержимое регистра DI

0Ch

2

Содержимое регистра DS

0Eh

2

Содержимое регистра ES

10h

2

= 0000h (резервировано)

12h

2

Идентификатор виртуальной машины

14h

2

Идентификатор процесса, т.е. сегмент его PSP

Примечание 1: если предполагается исполнять вызываемый процесс в рамках той же действующей системы DOS, то в качестве идентификатора виртуальной машины следует указывать значение 0000h.

Примечание 2: когда показанный здесь блок параметров используется для закрывания процесса с помощью INT 21\AX=5D01h (8.02-69), тогда во внимание принимаются только слова со смещениями 12h и 14h, а все остальное содержание блока игнорируется.

A.07-5 Совместное пользование номером прерывания.

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

Первым шагом к организации взаимодействия резидентных модулей явился предложенный фирмой IBM протокол ISP (= Interrupt Sharing Protocol),

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

– 635 –

Приложение А.07: Структуры данных для исполнения программ

Согласно протоколу ISP адрес вызова, вписываемый в таблицу прерываний, должен указывать на команду ближнего перехода на 16 байт вперед – туда, где начинается исполняемый код резидентного модуля. "Перепрыгиваемый" 16-байтный участок – это место для размещения блока данных. Состав размещаемых там данных показан в приведенной ниже таблице. Все смещения в таблице рассчитаны относительно адреса вызова обработчика прерывания.

Смещение

Длина

Содержание

00h

2

Команда перехода (EB 10) к исполняемому коду

02h

4

Адрес следующего обработчика в цепи

06h

2

Сигнатура 4Bh 42h (= "KB")

08h

1

= 00h

– очередной обработчик в цепи ссылок

 

 

= 80h

– первоначальный обработчик прерывания

09h

2

Адрес подпрограммы выгружения модуля,

 

 

 

оканчивающейся командой возврата RETF

0Bh

7

Резервировано (должны быть нули)

Примечание 1: далеко не все резидентные модули соответствуют протоколу ISP. Нередко его намеренно игнорируют, чтобы предотвратить прослеживание цепи ссылок или выгружение резидентного модуля.

A.07-6 Команды альтернативного мультиплексного прерывания.

При пользовании мультиплексным прерыванием INT 2F, рассматриваемым в разделе 8.03, несогласованные действия разработчиков могут приводить к назначению одинаковых идентификаторов разным резидентным модулям. Во

избежание вызванных этим конфликтов Ральф Браун предложил назначать идентификаторы не заранее по усмотрению разработчиков, а автоматически в процессе загрузки модулей. Идея Ральфа Брауна реализована альтернативным мультиплексным прерыванием INT 2D и регламентирована спецификацией AMIS (Alternate Multiplex Interrupt Specification). Материал данного раздела основан на спецификации AMIS версии 3.6. Помимо того, каждый резидентный модуль, пользующийся прерыванием INT 2D, должен поддерживать формирование прослеживаемой цепи ссылок согласно протоколу ISP (A.07-5).

Идентификатор для загружаемого модуля предложено искать посредством цикла вызовов мультиплексного прерывания INT 2D с кодом операции AL=00h и с последовательным перебором идентификаторов в регистре AH, начиная с AH=00h. Если какой-либо из загруженных ранее модулей уже считает идентификатор в регистре AH "своим", то он должен установить AL=FFh, возвратить в регистрах CH:CL номер версии, а в регистрах DX:DI – указатель на сигнатуру длиной до 80 байт, оканчивающуюся кодом 00h. Выход из цикла – по условию возврата

– 636 –

Приложение А.07: Структуры данных для исполнения программ

неизмененного значения AL = 00h: значит, на заявленный идентификатор никто не претендует, и загружаемый модуль вправе присвоить его себе.

Аналогичный цикл, только с другим условием окончания, организуют чтобы определить, загружен ли какой-либо конкретный модуль. При таких проверках центральную роль играет сигнатура, указатель на которую возвращается в регистрах DX:DI. Для идентификации модуля должно быть достаточно 16 байт сигнатуры, причем первые 8 байт выделяются названию фирмы или имени разработчика, а последующие 8 байт – названию программы или драйвера, загрузивших данный резидентный модуль. Допускаются сокращенные названия. Если название короче 8 байт, его следует дополнить до 8 байт пробелами (байтами 20h). Часть сигнатуры сверх 16 байт не обязательна, но может содержать полезные сведения. Проверка по сигнатуре помогает предотвратить повторную загрузку резидентных программ. Вместе с выяснением факта загрузки интересующего модуля становится известен присвоенный ему идентификатор, по которому можно запросить другие функции того же модуля.

Поскольку вызовы мультиплексного прерывания предполагают прослеживание цепи ссылок и выполняются медленно, постольку обращаться к специфичным функциям резидентных модулей через прерывание INT 2D нецелесообразно (хотя для этого допускается использовать коды операций свыше 10h). Предпочтителен иной путь – прямое обращение к функциям модулей командой CALL FAR (7.03-08). Чтобы получить адрес прямого обращения, нужно вызвать прерывание INT 2D с идентификатором конкретного загруженного модуля в регистре AH и с кодом операции 01h в регистре AL. Искомый адрес, возвращаемый в регистрах DX:BX, надо запомнить, и тогда им можно будет пользоваться многократно.

Помимо упомянутых операций с кодами AL=00h и AL=01h, спецификация AMIS предусматривает унификацию кодов еще нескольких операций, перечисленных в первом столбце приведенной ниже таблицы. Операции с ненулевыми кодами не обязательны для исполнения. Если в ответ на вызов модуль возвращает в регистре AL код статуса 00h, значит он не поддерживает данную операцию. Напротив, возврат статуса FFh означает, что запрошенная операция поддерживается и успешно выполнена. Отдельные операции допускают возврат иных значений кода статуса, позволяющих судить о состоянии резидентного модуля. Эти и некоторые другие особенности исполнения операций пояснены в примечаниях к таблице.

Код

Значение

Примечания

00h

Проверка наличия резидентного модуля в памяти

 

01h

Запрос адреса обращения к резидентному модулю

*1

02h

Деинсталляция резидентного модуля

*2

03h

Вызов резидентной программы на исполнение

*3

– 637 –

Приложение А.07: Структуры данных для исполнения программ

Продолжение таблицы А.07-6

 

 

04h

Запрос задействованных прерываний

*4

 

05h

Запрос списка "горячих" клавишей

*5

 

06h

Запрос об установленных программой драйверах

*6

Примечание 1: возврат статуса AL = 00h означает, что данный модуль не принимает обращения командой CALL FAR. Адрес в регистрах DX:BX действителен только при возврате статуса AL = FFh.

Примечание 2: при запросе деинсталляции в регистрах DX:BX должен быть указан адрес перехода после деинсталляции, хотя резидентный модуль может игнорировать этот адрес. Возвращаемые в регистре AL коды статуса (помимо 00h и FFh) означают следующее:

01h – неудача попытки деинсталляции;

02h – деинсталляция будет завершена позже;

03h – модуль не имеет деинсталлятора и остался активным; 04h – то же, что 03h, но модуль дезактивирован;

05h – попытку деинсталляции надо повторить позже;

06h – модуль дезактивирован, деинсталляция невозможна; 07h – то же, что 03h, но требуется удаление драйверов.

Возврат кодов статуса 03h, 04h или 07h означает необходимость пользования отдельной программой деинсталляции, причем для нее подлежащий удалению модуль должен возвратить в регистре BX сегментный адрес размещения своего исполняемого кода.

Примечание 3: возвращаемые в регистре AL коды статуса (помимо 00h и FFh) означают следующее:

01h – попытку активизации надо повторить позже;

02h – программа будет активизирована позже;

03h – программа уже активизирована;

04h – сбой при попытке активизации программы.

При коде статуса FFh активизируемая программа возвращает в регистре BX дополнительные сведения о своем состоянии (или просто обнуляет регистр BX). При коде статуса 04h дополнительные сведения возвращаются в регистрах BX и CX; в случае неизвестной причины сбоя эти регистры должны быть обнулены.

Примечание 4: при вызове операции 04h в регистре BL должен быть указан номер прерывания (кроме INT 2D), факт перехвата которого надлежит установить. Возвращаемые в регистре AL коды статуса (помимо 00h) означают следующее:

01h – результат проверки не определен;

02h – указанное прерывание перехвачено;

03h – то же, что 02h, плюс адрес обработчика – в DX:BX; 04h – в DX:BX – адрес списка перехваченных прерываний; FFh – указанное прерывание не перехвачено.

– 638 –

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]