Untitled
7. Приложения
7.1. Управляющие блоки MS-DOS
7.2. Контроллер прерываний 8259
7.3. Сегментная адресация памяти
7.4. Содержимое файла sysp.h
7.5 Содержимое файла sysp.inc
7.6. MS-DOS версии 5.0
7.1.1. Векторная таблица связи MS-DOS
7.1.2. Блок управления памятью MCB
7.1.3. Префикс программного сегмента PSP
7.1.4. Формат блока DDCB
7.1.5. Формат таблицы файлов DFT
7.1.6. Заголовок драйвера
7.1.7. Формат элемента массива дисковой информации
7.1.8. Заголовок EXE-файла
7.1.9. Атрибуты драйвера
7.1.10. Заголовок запроса
7.1.11. Слово состояния устройства
7.1.12. Коды ошибок
7.1.13. Блок BPB
7.1.14. Форматы запросов для различных команд
7.1.15. Команды драйвера
7.1.16. Коды идентификации типа компьютера
7.1.17. Таблица параметров для жестких дисков
7.1.18. Параметры флоппи-дисков
7.1.19. Таблица параметров дискеты
7.1.20. Таблица параметров жесткого диска
7.1.21. Команды контроллера НГМД
7.1.22. Регистры состояния контроллера
7.1.23. Код ошибки при работе с диском на уровне BIOS
7.1.24. Формат первого сектора жесткого диска
7.1.25. Элементы таблицы разделов диска
7.1.26. Формат записи BOOT для DOS версий до 4.0
7.1.27. Формат BPB для DOS версий до 4.0
7.1.28. Формат BOOT-сектора для MS-DOS версии 4.0
7.1.29. Расширенный блок параметров BIOS
7.1.30. Байт-описатель среды media
7.1.31. Обозначение кластеров в FAT
7.1.32. Формат дескриптора файла
7.1.33. Байт атрибутов файла
7.1.34. Формат поля времени
7.1.35. Формат даты обновления файла
7.1.36. Формат блока DDCB для версий 2.х и 3.х
7.1.37. Формат блока DDCB для DOS версии 4.х
7.1.38. Идентификатор BIOS
(-2) 2 | mcb_seg
| сегмент первого управляющего блока памяти (MCB)
|
(0) 4 | dev_cb
| указатель на первый блок управления устройствами DOS (DOS Device Control Block)
|
(+4) 4 | file_tab
| указатель на таблицу файлов DOS |
(+8) 4 | clock_dr
| указатель на драйвер CLOCK$, установленный или резидентный
|
(+12) 4 | con_dr
| указатель на актуальный драйвер CON, установленный или резидентный
|
| | ----------- DOS 2.x ----------------
|
(+16) 1 | num_lgdr
| число логических драйверов в системе |
(+17) 2 | max_btbl
| максимальное число байтов/блоков любого блочного устройства
|
(+19) 4 | disk_buf
| указатель на первый дисковый буфер |
(+23) - | null_dr
| начало драйвера NUL - первого драйвера в списке драйверов DOS
|
| | ----------- DOS 3.x, 4.x , 5.0-----------
|
(+16) 2 | max_btbl
| максимальное число байтов в блоке блочного устройства
|
(+18) 4 | disk_buf
| указатель на первый дисковый буфер |
(+22) 4 | drv_info
| укзатель на массив информации об устройствах
|
(+26) 4 | fcb_tabl
| указатель на таблицу FCB |
(+30) 2 | fcb_size
| размер таблицы FCB |
(+32) 1 | num_bdev
| число блочных устройств |
(+33) 1 | lastdriv
| значение LASTDRIVE в файле CONFIG.SYS (по умолчанию равно 5)
|
(+34) | null_dr
| начало драйвера NUL - первого драйвера в списке драйверов DOS
|
(0) 1 | type |
тип блока MCB (M или Z) |
(+1) 2 | owner |
параграф владельца блока (если 0, то блок описывает сам себя)
|
(+3) 2 | size |
число параграфов в этом блоке (один параграф имеет размер 16 байт)
|
(+5) 11 | reserve
| зарезервировано |
(0) 2 | int20h
| двоичный код команды int 20h (программы могут использовать эту команду для завершения своей работы)
|
(+2) 2 | mem_top
| нижняя граница доступной памяти в системе в параграфах
|
(+4) 1 | reserv1
| зарезервировано |
(+5) 5 | call_dsp
| команда вызова FAR CALL диспетчера MS-DOS
|
(+10) 4 | term_adr
| адрес завершения (Terminate Address)
|
(+14) 4 | cbrk_adr
| адрес обработчика Ctrl-Break |
(+18) 4 | crit_err
| адрес обработчика критической ошибки |
(+22) 2 | parn_psp
| сегмент PSP программы, запустившей данную программу (программы-родителя)
|
(+24) 20 | file_tab
| таблица открытых файлов, если здесь находятся байты 0FFH, то таблица не используется
|
(+44) 2 | env_seg
| сегмент блока памяти, содержащего переменные среды
|
(+46) 4 | ss_sp
| адрес стека SS:SP программы |
(+50) 2 | max_open
| максимальное число открытых файлов |
(+52) 4 | file_tba
| адрес таблицы открытых файлов |
(+56) 24 | reserv2
| зарезервировано |
(+80) 3 | disp |
диспетчер функций DOS |
(+83) 9 | reserv3
| зарезервировано |
(+92) 16 | fcb1
| форматируется как стандартный FCB, если первый аргумент командной строки содержит правильное имя файла
|
(+108) 20 | fcb2
| заполняется для второго аргумента командной строки аналогично fcb1
|
(+128) 1 | p_size
| число значащих символов в неформатированной области параметров, либо буфер обмена с диском DTA, назначенный по умолчанию
|
(+129) 127 | parm
| неформатированная область параметров, заполняется при запуске программы из командной строки
|
для DOS версий 2.х и 3.х:
(0) 1 | drv_num
| номер устройства (0 соответствует устройству А:, 1 - В: и т.д.)
|
(+1) 1 | drv_numd
| дополнительный номер устройства внутри драйвера
|
(+2) 2 | sec_size
| размер сектора в байтах |
(+4) 1 | clu_size
| число, на единицу меньшее количества секторов в кластере
|
(+5) 1 | clu_base
| число, являющееся степенью 2 числа секторов в кластере
|
(+6) 2 | boot_siz
| количество зарезервированных секторов (boot-сектора, начало корневого каталога)
|
(+8) 1 | fat_num
| количество копий FAT |
(+9) 2 | max_dir
| максимальное число дескрипторов файлов в корневом каталоге (т.е. максимальное число файлов, которое может содержать корневой каталог на этом устройстве)
|
(+11) 2 | data_sec
| номер первого сектора данных на диске (номер сектора, соответствующего кластеру номер 2)
|
(+13) 2 | hi_clust
| максимальное количество кластеров (равно увеличенному на 1 количеству кластерова данных)
|
(+15) 1 | fat_size
| количество секторов, занимаемых одной копией FAT
|
(+16) 2 | root_sec
| номер первого сектора корневого каталога |
(+18) 4 | drv_addr
| FAR-адрес заголовка драйвера, обслуживающего данное устройство
|
(+22) 1 | media
| байт описания среды носителя данных |
(+23) 1 | acc_flag
| флаг доступа, 0 означает, что к устройству был доступ
|
(+24) 4 | next |
адрес следующего блока DDCB, для последнего блока в поле смещения находится число FFFF
|
| | ----------- только для DOS 2.x --------------
|
(+28) 2 | dir_clu
| номер начального кластера текущего каталога (0 для корневого каталога)
|
(+30) 64 | dir_path
| строка в формате ASCIIZ, содержащая путь к текущему каталогу
|
| | --------------- DOS 3.х -------------------------
|
(+28) 2 | reserv1
| зарезервировано, обычно равно 0 |
(+30) 2 | built
| число FFFF в этом поле означает, что блок DDCB был построен
|
для DOS версии 4.х :
(0) 1 | drv_num
| номер устройства (0 соответствует устройству А:, 1 - В: и т.д.)
|
(+1) 1 | drv_numd
| дополнительный номер устройства внутри драйвера
|
(+2) 2 | sec_size
| размер сектора в байтах |
(+4) 1 | clu_size
| число, на единицу меньшее количества секторов в кластере
|
(+5) 1 | clu_base
| число, являющееся степенью 2 числа секторов в кластере
|
(+6) 2 | boot_siz
| количество зарезервированных секторов (boot-сектора, начало корневого каталога)
|
(+8) 1 | fat_num
| количество копий FAT |
(+9) 2 | max_dir
| максимальное число дескрипторов файлов в корневом каталоге (т.е. максимальное число файлов, которое может содержать корневой каталог на этом устройстве)
|
(+11) 2 | data_sec
| номер первого сектора данных на диске (номер сектора, соответствующего кластеру номер 2)
|
(+13) 2 | hi_clust
| максимальное количество кластеров (равно увеличенному на 1 количеству кластеров данных)
|
(+15) 1 | fat_size
| количество секторов, занимаемых одной копией FAT
|
(+16) 1 | reserv1
| зарезервировано |
(+17) 2 | root_sec
| номер первого сектора корневого каталога |
(+19) 4 | drv_addr
| FAR-адрес заголовка драйвера, обслуживающего данное устройство
|
(+23) 1 | media
| байт описания среды носителя данных |
(+24) 1 | acc_flag
| флаг доступа, 0 означает, что к устройству был доступ
|
(+25) 4 | next |
адрес следующего блока DDCB, для последнего блока в поле смещения находится число FFFF
|
(+29) 2 | reserv2
| зарезервироано |
(+31) 2 | built
| число FFFF в этом поле означает, что блок DDCB был построен
|
для DOS 3.х:
(0) 4 | next |
указатель на следущую таблицу файлов |
(+4) 2 | file_count
| количество файлов в этой таблице |
| | ----- Дальше идут блоки DFCB в количестве file_count штук -----
|
(0) 2 | handl_num
| количество файловых чисел, связанных с данным файлом (file handle)
|
(+2) 1 | access_mode
| режим доступа к файлу, заданный при открытии файла
|
(+3) 2 | reserv1
| зарезервировано |
(+5) 2 | dev_info
| информация IOCTL, полученная для устройства, на котором расположен этот файл (подробно формат и назначение этого поля будут расмотрены в главе, посвященной драйверам)
|
(+7) 4 | driver
| указатель на драйвер, обслуживающий устройство, содержащее файл
|
(+11) 2 | first_clu
| номер первого кластера, распределенного файлу
|
(+13) 2 | time |
время последнего изменения файла в упакованном формате
|
(+15) 2 | date |
дата последнего изменения файла в упакованном формате
|
(+17) 4 | fl_size
| размер файла в байтах |
(+21) 4 | offset
| текущее смещение внутри файла в байтах |
(+25) 2 | reserv2
| зарезервировано |
(+27) 2 | last_clu
| номер только что прочитанного кластера |
(+29) 3 | reserv3
| зарезервировано |
(+32) 11 | filename
| имя файла в формате FCB (имя выравнено на левую границу поля, дополнено пробелами до 8 символов, справа к нему прилегает 3 символа расширения без точки)
|
(+43) 2 | reserv4
| зарезервировано |
(+45) 2 | ownr_psp
| PSP программы, открывшей файл |
(+47) 2 | reserv5
| зарезервировано |
для DOS 4.х:
(0) 4 | next |
указатель на следущую таблицу файлов |
(+4) 2 | file_count
| количество файлов в этой таблице |
| | -------- Дальше идут блоки DFCB в количестве file_count штук ------
|
(0) 2 | handl_num
| количество файловых чисел, связанных с данным файлом (file handle)
|
(+2) 1 | access_mode
| режим доступа к файлу, заданный при открытии файла
|
(+3) 2 | reserv1
| зарезервировано |
(+5) 2 | dev_info
| информация IOCTL, полученная для устройства, на котором расположен этот файл (подробно формат и назначение этого поля будут расмотрены в главе, посвященной драйверам)
|
(+7) 4 | driver
| указатель на драйвер, обслуживающий устройство, содержащее файл
|
(+11) 2 | first_clu
| номер первого кластера, распределенного файлу
|
(+13) 2 | time
| время последнего изменения файла в упакованном формате
|
(+15) 2 | date
| дата последнего изменения файла в упакованном формате
|
(+17) 4 | fl_size
| размер файла в байтах |
(+21) 4 | offset
| текущее смещение внутри файла в байтах |
(+25) 2 | reserv2
| зарезервировано |
(+27) 2 | reserv7
| зарезервировано |
(+29) 3 | reserv3
| зарезервировано |
(+32) 1 | reserv4
| зарезервировано |
(+33) 11 | filename
| имя файла в формате FCB (имя выравнено на левую границу поля, дополнено пробелами до 8 символов, справа к нему прилегает 3 символа расширения без точки)
|
(+44) 2 | reserv5
| зарезервировано |
(+46) 2 | ownr_psp
| PSP программы, открывшей файл |
(+48) 2 | reserv6
| зарезервировано |
(+50) 2 | last_clu
| номер только что прочитанного кластера |
(+52) 4 | reserv8
| зарезервировано |
(0) 4 | next |
указатель на заголовок следующего драйвера. Если смещение адреса следующего драйвера равно FFFF, это последний драйвер в цепочке
|
(+4) 2 | attrib
| атрибуты драйвера |
(+6) 2 | strateg
| смещение программы стратегии драйвера |
(+8) 2 | interrupt
| смещение программы обработки прерывания для драйвера
|
(+10) 8 | dev_name
| имя устройства для символьных устройств или количество обслуживаемых устройств для блочных устройств.
|
(0) 64 | path |
текущий путь доступа для диска |
(+64) 2 | reserv1
| зарезервировано |
(+66) 2 | reserv2
| зарезервировано |
(+68) 1 | reserv3
| зарезервировано |
(+69) 4 | ddcb |
адрес соответствующего DDCB |
(+73) 2 | cdir_clu
| первый кластер текущего каталога на диске. 0 соответствует корневому каталогу, -1 - если к диску еще не обращались
|
(+75) 2 | reserv4
| зарезервировано |
(+77) 2 | reserv5
| зарезервировано |
(+79) 2 | reserv6
| зарезервировано |
| | ---------------- для DOS 4.х -----------------
|
(+81) 7 | reserv7
| зарезервировано |
(0) 2 | signature
| два байта 'MZ' (4Dh, 5Ah), индентифицирующие файл в формате EXE
|
(+2) 2 | part_pag
| длина последней страницы программы в байтах (страница содержит 512 байт)
|
(+4) 2 | file_size
| размер программы в страницах по 512 байт |
(+6) 2 | rel_item
| число элементов в таблице расположения сегментов
|
(+8) 2 | hdr_size
| размер заголовка файла в параграфах (длина параграфа - 16 байт)
|
(+10) 2 | min_mem
| минимальное количество памяти в параграфах, которое нужно зарезервировать в памяти за концом загруженной программы
|
(+12) 2 | max_mem
| максимальное количество памяти в параграфах, которое нужно зарезервировать в памяти за концом загруженной программы
|
(+14) 2 | ss_reg
| величина смещения от начала программы, которая используется для загрузки сегментного регистра стека SS
|
(+16) 2 | sp_reg
| величина смещения от начала программы, которая используется для загрузки регистра SP
|
(+18) 2 | chk_summ
| контрольная сумма всех слов в файле |
(+20) 2 | ip_reg
| значение для регистра IP, которое будет использовано при начальном запуске программы
|
(+22) 2 | cs_reg
| смещение от начала программы для установки сегментного регистра кода CS
|
(+24) 2 | relt_off
| смещение от начала файла таблицы расположения сегментов программы
|
(+26) 2 | overlay
| номер оверлея, равен 0 для основного модуля
|
Символьное устройство
Бит | Назначение
|
0 | 1 - драйвер обслуживает стандартное устройство ввода;
0 - этот драйвер не обслуживает стандартное устройство ввода
|
1 | 1 - драйвер обслуживает стандартное устройство вывода;
0 - драйвер не обслуживает стандартное устройство вывода
|
2 | 1 - это драйвер стандартного устройства NUL;
0 - драйвер не обслуживает устройство NUL
|
3 | 1 - драйвер обслуживает часы
|
4 | Зарезервировано, бит должен быть равен 0
|
5 | Зарезервировано, бит должен быть равен 0
|
6 | 1 - разрешено использование драйвером функций GENERIC IOCTL (для версий DOS, более поздних, чем 3.2);
0 - функции GENERIC IOCTL не поддерживаются
|
7-10 | Эти биты зарезервированы и должны быть равны 0
|
11 | 1 - поддерживаются функции открытия/закрытия устройства (OPEN/CLOSE) для символьных устройств;
0 - функции OPEN/CLOSE для символьных устройств не поддерживаются
|
12 | Зарезервировано, бит должен быть равен 0
|
13 | 1 - для символьных устройств поддерживается функция вывода до получения состояния занятости устройства;
0 - функция вывода до состояния занятости не поддерживается
|
14 | 1 - поддерживаются функции IOCTL;
0 - функции IOCTL не поддерживаются
|
15 | 1 - символьное устройство;
0 - блочное устройство
|
Блочное устройство
Бит | Назначение
|
0 | Зарезервировано, бит должен быть равен 0
|
1 | 1 - драйвер поддерживает 32-битовую адресацию сектора (для версий DOS, начиная с 4.00 и более поздних); если установлен этот бит, поле номера сектора всех запросов является двойным словом, добавляемым в конец заголовка запроса, старое поле номера сектора должно содержать -1);
0 - используется 16-битовая адресация сектора
|
2-5 | Эти биты зарезервированы и должны быть равны 0
|
6 | 1 - поддерживаются логические устройства (используется блочными драйверами для управления "виртуальными" флоппи-дисками, создаваемые драйвером DRIVER.SYS в DOS версии 3.2 и более поздних версиях);
0 - логические устройства для блочных драйверов не поддерживаются;
|
7-10 | Эти биты зарезервированы и должны быть равны 0
|
11 | 1 - единица в этом бите означает, что драйвер поддерживает функцию проверки замены носителя данных в устройстве (например, замены дискеты), используется для DOS версий 3.00 и более поздних;
0 - для блочных устройств функция проверки замены носителя данных не поддерживается
|
12 | Зарезервировано, бит должен быть равен 0
|
13 | 1 - драйвер не использует стандартное IBM-устройство, и необходимо выдать запрос на построение блока параметров BIOSBIOS BPB;
0 - используется IBM-устройство
|
14 | 1 - поддерживаются функции IOCTL;
0 - функции IOCTL не поддерживаются
|
15 | 1 - символьное устройство;
0 - блочное устройство
|
(0) 1 | size |
Длина запроса в байтах (длина заголовка запроса плюс длина переменной части запроса)
|
(+1) 1 | unit |
Номер устройства (используется для блочных устройств, указывает, с каким именно устройством, обслуживаемым драйвером, будет работать операционная система)
|
(+2) 1 | cmd |
Код команды, которую требуется выполнить (может иметь значение от 0 до 18h)
|
(+3) 2 | status
| Слово состояния устройства, заполняется драйвером перед возвратом управления операционной системе
|
(+5) 8 | reserved
| Зарезервировано |
Бит | Назначение
|
0-7 | Код ошибки устройства (если команда выполнилась с ошибкой и драйвер установил признак ошибки (бит 15) в единицу, то в это поле он должен записать код ошибки).
|
8 | Команда выполнена. Этот бит всегда устанавливается драйвером перед тем, как он возвращает управление операционной системе.
|
9 | Занято. Этот бит устанавливается обработчиком команды, когда физическое устройство занято выполнением предыдущей операции и поэтому не может выполнить требуемую команду. Этот бит используется также для передачи такой информации, как "буфер клавиатуры не пуст", "среда носителя данных заменяемая" (в команде проверки возможности замены среды носителя данных).
|
10-14 | Зарезервировано.
|
15 | Признак ошибки. Устанавливается драйвером, когда он не может обработать запрос или произошла физическая либо логическая ошибка при обработке правильного запроса. Биты 0-7 при этом должны содержать код ошибки.
|
Код | Описание
|
0 | Нарушение защиты от записи. Была предпринята попытка записи информации на защищенное от записи устройство.
|
1 | Неизвестное устройство.
|
2 | Устройство не готово.
|
3 | Неизвестная команда. Затребованная команда не поддерживается драйвером.
|
4 | Ошибка CRC. При выполнении команды обнаружена ошибка циклического кода проверки.
|
5 | Неправильная длина запроса. Поле длины в заголовке запроса содержит неверное значение.
|
6 | Ошибка при поиске дорожки (дорожка не найдена).
|
7 | Неизвестный носитель данных.
|
8 | Сектор не найден.
|
9 | Нет бумаги в принтере.
|
0Ah | Ошибка записи. |
0Bh | Ошибка чтения. |
0Ch | Общая ошибка. |
0Dh | Зарезервировано.
|
0Eh | Зарезервировано.
|
0Fh | Неразрешенная замена диска (только для DOS версии 3.0 и более поздних версий).
|
(0) 2 | sect_siz
| Количество байтов в одном секторе диска. |
(+2) 1 | clustsiz
| Количество секторов в одном кластере. |
(+3) 2 | res_sect
| Количество зарезервированных секторов. |
(+5) 1 | fat_cnt
| Количество таблиц FAT. |
(+6) 2 | root_siz
| Максимальное количество файловых дескрипторов, содержащихся в корневом каталоге диска.
|
(+8) 2 | tot_sect
| Общее количество секторов на носителе данных (в разделе DOS).
|
(+10) 1 | media
| Байт-описатель среды носителя данных. |
(+11) 2 | fat_size
| Количество секторов, занимаемых одной копией FAT.
|
(0) 13 | header
| Заголовок запроса. |
(+13) 1 | n_units
| Количество устройств, обслуживаемых драйвером. Это поле заполняется только блочным драйвером.
|
(+14) 4 | end_addr
| Конечный FAR-адрес резидентной части кода драйвера. В это поле драйвер записывает адрес байта памяти, следующего за той частью кода драйвера, которая должна стать резидентной.
|
(+18) 4 | parm |
FAR-адрес строки параметров инициализации драйвера из файла CONFIG.SYS. Эта строка содержит все, что находится в строке файла после команды 'DEVICE=', она заканчивается символами перевода строки и возврата каретки 0Ah, 0Dh. При возврате драйвер блочного устройства должен записать в это поле адрес массива указателей на блоки параметров BIOSBIOS (BPB), по одному указателю на каждое устройство, обслуживаемое драйвером.
|
(+22) 1 | drive
| Номер устройства. Для версии DOS 3.0 и более поздних версий в это поле при загрузке драйвера операционная система заносит номер, назначенный устройству, обслуживаемому драйвером. Например, для устройства А:это 0, для B: - 1 и т.д.
|
- 1 - Проверка замены носителя
(0) 13 | header
| Заголовок запроса. |
(+13) 1 | media
| В этом поле драйверу передается байт-описатель среды носителя данных, с которым DOS работала раньше.
|
(+14) 1 | reply
| В это поле драйвер должен поместить ответ о факте замены среды:
1 - диск не заменялся;
0 - неизвестно;
-1 - диск был заменен.
|
(+15) 4 | vol_id
| Указатель на предыдущую метку тома (если установлен бит 11 слова атрибута устройства и диск был заменен)
|
(0) 13 | header
| Заголовок запроса. |
(+13) 1 | media
| В этом поле драйверу передается байт-описатель среды носителя данных, с которым DOS работала раньше.
|
(+14) 4 | buf_adr
| Адрес буфера обмена. Содержимое этого буфера при вызове драйвера зависит от утановки бита 13 слова атрибутов устройства (IBM-формат). Если этот бит равен 0 (устройство формата IBM), буфер содержит первый сектор первой копии FAT. В противном случае указатель установлен на буфер свободного сектора.
|
(+18) 4 | bpb_adr
| Указатель на новый BPB, записывается в это поле драйвером.
|
- 3, 4, 8, 9, 0Ch - Чтение/Запись.
(0) 13 | header
| Заголовок запроса. |
(+13) 1 | media
| В этом поле драйверу передается байт-описатель среды носителя данных.
|
(+14) 4 | buf_adr
| Адрес буфера для передачи данных. |
(+18) 2 | count
| Количество передаваемых байтов для символьных устройств или секторов для блочных устройств.
|
(+20) 2 | sector
| Номер начального сектора, если драйвер использует 16-битовую адресацию секторов или -1 для 32-битовой адресации. Это поле не используется символьными драйверами.
|
(+22) 4 | vol_id
| Указатель на метку тома в формате ASCIIZ. Возвращается блочным драйвером, если он выставляет ошибку 15 (неправильная смена диска). Это поле должно содержать ссылку на метку требуемого диска.
|
(+26) 4 | sect32
| Номер начального сектора, если содержимое поля sector равно -1. Первым идет старшее слово номера сектора. Если обнаружена ошибка с номером 15, в это поле записывается указатель на метку тома.
|
(0) 13 | header
| Заголовок запроса. |
(+13) 1 | byte |
В это поле драйвер записывает извлеченный из буфера байт, который будет считан по следующей команде ввода.
|
- 6, 0Ah - Проверит состояние ввода/вывода.
Для команд проверки состояния запрос состоит только из заголовка,
область переменного формата отсутствует.
- 7 - Сброс буфера устройства ввода.
- 11 - Сброс буфера устройства вывода.
Запрос состоит только из заголовка.
- 0Dh, 0Eh - Открыть/Закрыть устройство.
Запрос для этих команд состоит только из заголовка.
- 15 - Проверка сменяемости диска.
Запрос состоит только из заголовка.
- 19 - Общее управление вводом/выводом (GENERIC_IOCTL).
(0) 13 | header
| Заголовок запроса. |
(+13) 1 | funct
| Это поле содержит код функции команды общего IOCTL.
|
(+14) 1 | subfunc
| Код подфункции для функции funct. |
(+15) 2 | si_reg
| Значение регистра SI при вызове функции 44h прерывания 21h. Эта функция DOS предназначена для управления вводом/выводом.
|
(+17) 2 | di_reg
| Значение, передаваемое при вызове функции 44h прерывания 21h через регистр DI.
|
(+19) 4 | buf |
Указатель на буфер данных, содержащий управляющую информацию для устройства или предназначенный для приема информации от устройства.
|
- 23 - Получить активное логическое устройство.
- 24 - Установить активное логическое устройство.
(0) 13 | header
| Заголовок запроса. |
(+13) 1 | unit |
Код логического устройства, которое должно стать активным при использовании команды 24, или код активного устройства, помещаемый драйвером по команде 23.
|
(+14) 1 | cmd |
Код команды. |
(+15) 4 | status
| Слово состояния. |
(+19) 4 | reserved
| Зарезервировано. |
0 | Инициализация |
1 | Проверка смены носителя данных
|
2 | Построить блок BPB
|
3 | Чтение IOCTL |
4 | Чтение |
5 | Неразрушающее чтение
|
6 | Проверка состояния ввода
|
7 | Сброс буферов ввода
|
8 | Запись |
9 | Запись с проверкой
|
10 | Проверка состояния вывода
|
11 | Сброс буферов вывода
|
12 | Запись IOCTL |
13 | Открыть устройство
|
14 | Закрыть устройство
|
15 | Проверка возможности смены носителя данных
|
16 | Зарезервировано
|
17 | Зарезервировано
|
18 | Зарезервировано
|
19 | Общее управление вводом/выводом (GENERIC IOCTL)
|
20 | Получить текущее логическое устройство
|
21 | Установить логическое устройство
|
FF | оригинальный IBM PC |
FE | XT, Portable PC |
FD | PCjr |
FC | AT |
FB | XT с памятью 640 К на материнской плате
|
F9 | Convertible PC |
+
¦Тип ¦ Количество ¦ Количество ¦ Емкость диска
¦ ¦ цилиндров ¦ головок ¦ в байтах
++++
¦ 1 ¦ 306 ¦ 4 ¦ 10.653.696
¦ 2 ¦ 615 ¦ 4 ¦ 21.411.840
¦ 3 ¦ 615 ¦ 6 ¦ 32.117.760
¦ 4 ¦ 940 ¦ 8 ¦ 65.454.080
¦ 5 ¦ 940 ¦ 6 ¦ 49.090.560
¦ 6 ¦ 615 ¦ 4 ¦ 21.411.840
¦ 7 ¦ 462 ¦ 8 ¦ 32.169.984
¦ 8 ¦ 733 ¦ 5 ¦ 31.900.160
¦ 9 ¦ 900 ¦ 15 ¦ 117.504.000
¦ 10 ¦ 820 ¦ 3 ¦ 21.411.840
¦ 11 ¦ 855 ¦ 5 ¦ 37.209.600
¦ 12 ¦ 855 ¦ 7 ¦ 52.093.440
¦ 13 ¦ 306 ¦ 8 ¦ 21.307.392
¦ 14 ¦ 733 ¦ 7 ¦ 44.660.224
¦ 15 ¦ 0 ¦ 0 ¦ 0
¦ 16 ¦ 612 ¦ 4 ¦ 21.307.392
¦ 17 ¦ 977 ¦ 5 ¦ 42.519.040
¦ 18 ¦ 977 ¦ 7 ¦ 59.526.656
¦ 19 ¦ 1024 ¦ 7 ¦ 62.390.272
¦ 20 ¦ 733 ¦ 5 ¦ 31.900.160
¦ 21 ¦ 733 ¦ 7 ¦ 44.660.224
¦ 22 ¦ 733 ¦ 5 ¦ 31.900.160
¦ 23 ¦ 306 ¦ 4 ¦ 10.653.696
¦ 24 ¦ 977 ¦ 5 ¦ 42.519.040
¦ 25 ¦ 1024 ¦ 9 ¦ 80.216.064
¦ 26 ¦ 1224 ¦ 7 ¦ 74.575.872
¦ 27 ¦ 1224 ¦ 11 ¦ 117.190.656
¦ 28 ¦ 1224 ¦ 15 ¦ 159.805.440
¦ 29 ¦ 1024 ¦ 8 ¦ 71.303.168
¦ 30 ¦ 1024 ¦ 11 ¦ 98.041.856
¦ 31 ¦ 918 ¦ 11 ¦ 87.892.992
¦ 32 ¦ 925 ¦ 9 ¦ 72.460.800
¦ 33 ¦ 1024 ¦ 10 ¦ 89.128.960
¦ 34 ¦ 1024 ¦ 12 ¦ 106.954.752
¦ 35 ¦ 1024 ¦ 13 ¦ 115.867.648
¦ 36 ¦ 1024 ¦ 14 ¦ 124.780.544
¦ 37 ¦ 1024 ¦ 2 ¦ 17.825.792
¦ 38 ¦ 1024 ¦ 16 ¦ 142.606.336
¦ 39 ¦ 918 ¦ 15 ¦ 119.854.080
¦ 40 ¦ 820 ¦ 6 ¦ 42.823.680
+----
++
¦Тип¦Емкость,¦Диаметр,¦Количество секторов¦Количество¦
¦ ¦Кбайтов ¦дюймы ¦на одну дорожку ¦цилиндров ¦
+++++¦
¦ 1 ¦ 360 ¦ 5 ¦ 9 ¦ 40 ¦
¦ 2 ¦ 1200 ¦ 5 ¦ 15 ¦ 80 ¦
¦ 3 ¦ 720 ¦ 3 ¦ 9 ¦ 40 ¦
¦ 4 ¦ 1440 ¦ 3 ¦ 18 ¦ 80 ¦
++
- 1 srt_hut
Биты 0...3 - SRT (Step Rate Time) - задержка для переключения головок, лежит в пределах 1-16 мс и задается с интервалом 1 мс (0Fh - 1mc, 0Eh - 2 mc, 0Dh - 3 mc, ...);
биты 4...7 - задержки разгрузки головки, лежит в пределах 16-240 мс и задается с интервалом 16 мс (1 - 16 mc, 2 - 32 mc, ..., 0Fh - 240 mc).
(+1) 1 dma_hlt
Бит 0 - значение этого бита, равное 1, говорит о том, что используется прямой доступ к памяти (DMA);
биты 2...7 - время загрузки головок HLT_- интервал между сигналом загрузки головок и началом операции чтение/запись, лежит в пределах 2-254 мс и задается с интервалом 2 мс (1 - 2 mc, 2 - 4 mc, ..., 0FFh - 254 mc).
(+2) 1 motor_w
Задержка перед выключением двигателя.
(+3) 1 sec_size
Код размера сектора в байтах (0 - 128 байтов, 1 - 256, 2 - 512, 3 - 1024).
(+4) 1 eot
Номер последнего сектора на дорожке
(+5) 1 gap_rw
Длина межсекторного промежутка для чтения/записи.
(+6) 1 dtl
Максимальная длина передаваемых данных, используется когда не задана длина сектора.
(+7) 1 gap_f
Длина межсекторного промежутка для опрации форматирования.
(+8) 1 fill_char
Байт-заполнитель для форматирования (обычно используется F6h).
(+9) 1 hst
Время установки головки в миллисекундах.
(+10) 1 mot_start
Время запуска двигателя в 1/8 долях секунды.
- 2 max_cyl
Максимальное количество цилиндров на диске.
(+2) 1 max_head
Максимальное количество магнитных головок.
(+3) 2 srwcc
Начальный цилиндр для предварительной записи (Starting reduced-write current cylinder).
(+5) 2 swpc
Начальный цилиндр для предварительной компенсации при записи (Starting write precompensation cylinder).
(+7) 1 max_ecc
Максимальная длина блока коррекции ошибок ECC (Maximum ECC data burst length).
(+8) 1 dstopt
Опции устройства:
бит 7 - запрет восстановления;
бит 6 - запрет восстановления по блоку коррекции ошибок ECC (Error Correction Code);
биты 2-0 - опции устройства.
(+9) 1 st_del
Стандартная величина задержки.
(+10) 1 fm_del
Величина задержки для форматирования диска.
(+11) 1 chk_del
Величина задержки для проверки диска.
(+12) 4 reserve
Зарезервировано.
Команда Байты команды
Чтение ++
данных ¦MT ¦MFM¦SK ¦ 0 ¦ 0 ¦ 1 ¦ 1 ¦ 0 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Чтение удаленных ++
данных ¦MT ¦MFM¦SK ¦ 0 ¦ 1 ¦ 1 ¦ 0 ¦ 0 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Запись ++
данных ¦MT ¦MFM¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ 0 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Запись удаленных ++
данных ¦MT ¦MFM¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ 0 ¦ 1 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Чтение данных ++
с дорожки ¦MT ¦MFM¦SK ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Сканирование до ++
"равно" ¦MT ¦MFM¦SK ¦ 1 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Сканирование до ++
"меньше" или ¦MT ¦MFM¦SK ¦ 1 ¦ 1 ¦ 0 ¦ 0 ¦ 1 ¦
"равно" ++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Сканирование до ++
"больше" или ¦MT ¦MFM¦SK ¦ 1 ¦ 1 ¦ 1 ¦ 0 ¦ 1 ¦
"равно" ++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Форматирование ++
дорожки ¦ 0 ¦MFM¦ 0 ¦ 0 ¦ 1 ¦ 1 ¦ 0 ¦ 1 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Считывание ++
индексных ¦ 0 ¦MFM¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ 1 ¦ 1 ¦
данных ++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Инициализация ++
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 1 ¦ 1 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦
++
Чтение состояния ++
прерывания ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ 0 ¦ 0 ¦
++
Определить ++
параметры ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 1 ¦
++
Чтение ++
состояния ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ 0 ¦
накопителя ++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Поиск ++
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 1 ¦ 1 ¦ 1 ¦
++++++++¦
¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦HDS¦DS1¦DS0¦
++
Байты параметров, которые должны следовать за командами и байты
результата, которые процессор должен считать после выполнения
команды:
Команда Байты Байты
параметров результата
Чтение данных C, H, R, N, EOT, ST0, ST1, ST2,
EOT, GPL, DTL C, H, R, N
Чтение удаленных
данных
Запись данных
Запись удаленных
данных
Чтение данных
с дорожки
Сканирование до
"равно"
Сканирование до
"меньше" или
"равно"
Сканирование до
"больше" или
"равно"
Форматирование N, SC, GPL, D ST0, ST1, ST2,
дорожки C, H, R, N
Чтение индексных отсутствуют ST0, ST1, ST2,
данных C, H, R, N
Инициализация отсутствуют отсутствуют
Чтение состояния отсутствуют ST0, PCN
прерывания
Определить 1 байт: отсутствуют
параметры мл. тетрада - HUT
ст. тетрада - SRT
2 байт:
бит 0 - ND
биты 1-7 - HLT
Чтение состояния отсутствуют ST3
накопителя
Поиск C отсутствуют
Формат регистра ST0:
Биты Название Назначение
1, 0 US1, US2 Эти биты содержат код накопителя при
прерывании.
2 HD Номер головки.
3 NC Накопитель не готов, устанавливается,
если накопитель не готов выполнить
команду чтения или записи.
4 EC Сбой оборудования
5 SE Завершена команда "Поиск"
7, 6 I, C Код прерывания:
00 - нормальное завершение;
01 - аварийное завершение;
10 - некорректная команда
11 - нет готовности дисковода.
Формат регистра ST1:
Биты Название Назначение
0 MA Пропуск адресной метки. Этот бит
устанавливается в 1, если контроллер
не может найти адресную метку
1 NN Защита записи, устанавливается , если
при выполнении операции контроллер
получает от дисковода сигнал защиты
записи.
2 ND Не найден сектор.
3 - Зарезервирован
4 OR Переполнение, процессор не успевает
выполнять обмен данными с контроллером
5 DE Ошибка в данных при проверке
контрольной суммы
6 - Зарезервирован.
7 EN Несуществующий сектор, устанавливается,
когда контроллер пытается прочесть
сектор с адресом, большим
существующего.
Формат регистра ST2:
Биты Название Назначение
0 MD Пропущен адресный маркер в поле данных.
1 BC Нечитающаяся дорожка.
2 SN Ошибка сканирования. Устанавливается,
если при выполнении команды
сканирования контроллер не может
найти требуемую дорожку.
3 SH Сканирование выполнено, дорожка
найдена.
4 WC Ошибка адреса дорожки.
5 DD Ошибка в поле данных.
6 CM Во время операции чтения или
сканирования не обнаружен сектор с
с маркером удаленных данных.
7 - Зарезервирован.
Формат регистра ST3:
Биты Название Назначение
1, 0 US1, US2 Код выбранного дисковода.
2 HD Номер выбранной головки.
3 TS Используется режим двухсторонней
записи.
4 T0 Головка установлена на дорожку 0.
5 RDY Дисковод готов к работе.
6 WP Защита записи на диске.
7 FT Неисправность дисковода.
В форматах команд и таблицах используются следующие обозначения:
MT | двухсторонняя операция
|
MFM | двойная/одинарная плотность записи
|
SK | пропуск удаленных данных
|
HDS | номер головки для двухстороннего накопителя
|
DS1, DS0 | номер выбираемого накопителя
|
C | номер цилиндра |
H | номер головки для двухстороннего накопителя
|
R | номер сектора |
N | число байтов в секторе
|
EOT | номер последнего сектора на дорожке
|
GPL | размер промежутка |
DTL | число считываемых/записываемых байтов
|
SC | число секторов в цилиндре
|
D | данные |
PCN | номер цилиндра после выполнения команды
|
чтения состояния прерывания |
|
SRT | время шага, мс |
HUT | время разгрузки головки
|
HLT | время загрузки головки
|
ND | режим прерывания |
NCN | номер цилиндра после поиска
|
00h | Успешное завершение операции
|
01h | Неправильная команда |
02h | Не найдена адресная метка
|
03h | Попытка записи на диск, защищенный от записи
|
04h | Сектор не найден |
05h | Ошибка при сбросе (НМД)
|
06h | Произошла замена дискеты
|
07h | Неправильные параметры дисковода (НМД)
|
08h | Переполнение канала ПДП (НГМД)
|
09h | Переход за границу 64К при работе с ПДП
|
0Ah | Обнаружен плохой сектор (НМД)
|
0Bh | Обнаружена плохая дорожка (НМД)
|
0Ch | Неправильный номер дорожки
|
0Dh | Неправильный номер сектора при форматировании (НМД)
|
0Eh | Обнаружена адресная метка управляющих данных (НМД)
|
0Fh | Ошибка ПДП (НМД) |
10h | Обнаружена ошибка в CRC/ECC
|
11h | Данные скорректированы с использованием ECC (НМД)
|
20h | Сбой контроллера |
40h | Сбой при поиске дорожки
|
80h | Таймаут - программа не успевает обрабатывать данные
|
AAh | Дисковод не готов (НМД)
|
BBh | Неизвестная ошибка (НМД)
|
CCh | Сбой при записи (НМД)
|
E0h | Ошибка регистра состояния (НМД)
|
FFh | Ошибка операции считывания (НМД)
|
Смещение Размер Содержимое
(+0) 1BEh Загрузочная запись - программа,
которая загружается и выполняется
во время начальной загрузки
операционной системы
(+1BEh) 10H Элемент таблицы разделов диска
(+1CEh) 10H Элемент таблицы разделов диска
(+1DEh) 10H Элемент таблицы разделов диска
(+1EEh) 10H Элемент таблицы разделов диска
(+1FEh) 2 Признак таблицы разделов - 55AAh
Смещение Размер Содержимое
(+0) 1 Признак активного раздела:
0 - раздел не активный;
80h - раздел активный.
(+1) 1 Номер головки для начального сектора
раздела.
(+2) 2 Номер сектора и цилиндра для начального
сектора раздела в формате функции чтения
сектора INT_13h.
(+4) 1 Код системы:
0 - неизвестная система;
1, 4 - DOS;
5 - расширенный раздел DOS.
(+5) 1 Номер головки для последнего сектора
раздела.
(+6) 2 Номер сектора и цилиндра для последнего
сектора раздела в формате функции чтения
сектора INT_13h.
(+8) 4 Относительный номер сектора начала
раздела.
(+12) 4 Размер раздела в секторах.
Смещение Размер Содержимое
(+0) 3 Команда JMP xxxx - переход типа NEAR на
программу начальной загрузки
(+3) 8 Название фирмы-производителя
операционной системы и версия,
например: "IBM 4.0"
(+11) 13 BPB - блок параметров BIOS
(+24) 2 Количество секторов на дорожке
(+26) 2 Количество головок (поверхностей диска)
(+28) 2 Количество скрытых секторов, эти сектора
могут использоваться для схемы
разбиения физического диска на разделы
(0) 2 sect_siz Количество байтов в одном секторе диска.
(+2) 1 clustsiz Количество секторов в одном кластере.
(+3) 2 res_sect Количество зарезервированных секторов.
(+5) 1 fat_cnt Количество таблиц FAT.
(+6) 2 root_siz Максимальное количество дескрипторов файлов,
содержащихся в корневом каталоге диска.
(+8) 2 tot_sect Общее количество секторов на носителе данных
(в разделе DOS).
(+10) 1 media Байт-описатель среды носителя данных.
(+11) 2 fat_size Количество секторов, занимаемых одной
копией FAT.
Смещение Размер Содержимое
(+0) 3 Команда JMP xxxx - переход типа NEAR на
программу начальной загрузки
(+3) 8 Название фирмы-производителя
операционной системы и версия,
например: "IBM 4.0"
(+11) 25 Extended BPB - расширенный блок
параметров BIOS
(+36) 1 Физический номер дисковода (0 -флоппи,
80h - жесткий диск)
(+37) 1 Зарезервировано
(+38) 1 Символ ')' - признак расширенной
загрузочной записи DOS 4.0
(+39) 4 Серийный номер диска (Volume Serial
Number), создается во время
форматирования диска
(+43) 11 Метка диска (Volume Label)
(+54) 8 Зарезервировано, обычно содержит
запись типа 'FAT12 ', которая
идентифицирует формат таблицы размещения
файлов FAT
- 2 sect_siz
Количество байтов в одном секторе диска.
(+2) 1 clustsiz
Количество секторов в одном кластере.
(+3) 2 res_sect
Количество зарезервированных секторов.
(+5) 1 fat_cnt
Количество таблиц FAT.
(+6) 2 root_siz
Максимальное количество дескрипторов файлов, содержащихся в корневом каталоге диска.
(+8) 2 tot_sect
Общее количество секторов на носителе данных (в разделе DOS).
(+10) 1 media
Байт-описатель среды носителя данных.
(+11) 2 fat_size
Количество секторов, занимаемых одной копией FAT.
--------------- Расширение стандартного BPB --------------
(+13) 2 sectors
Количество секторов на дорожке
(+15) 2 heads
Количество магнитных головок
(+17) 2 hidden_l
Количество скрытых секторов для раздела, который по размеру меньше 32 мегабайтов.
(+19) 2 hidden_h
Количество скрытых секторов для раздела, превышающего по размеру 32 мегабайта. (Только для DOS 4.0).
(+21) 4 tot_secs
Общее количество секторов на логическом диске для раздела, превышающего по размеру 32 мегабайта.
FFh - 2 стороны, 8 секторов на дорожке;
FEh - 1 сторона, 8 секторов на дорожке;
FDh - 2 стороны, 9 секторов на дорожке;
FCh - 1 сторона, 9 секторов на дорожке;
F9h - 2 стороны, 15 секторов на дорожке;
F8h - жесткий диск.
FAT12 FAT16 Что означает
000h 0000h Свободный кластер
ff0h - ff6h fff0h - fff6h Зарезервированный кластер
ff7h fff7h Плохой кластер
ff8h - fffh fff8h - ffffh Последний кластер в списке
002h - fefh 0002h - ffefh Номер следующего кластера
в списке
Смещение Размер Содержимое
(+0) 8 Имя файла или каталога, выравненное
на левую границу и дополненное пробелами.
(+8) 3 Расширение имени файла, выравненное
на левую границу и дополненное пробелами.
(+11) 1 Атрибуты файла.
(+12) 10 Зарезервировано.
(+22) 2 Время создания файла или время
его последней модификации.
(+24) 2 Дата создания файла или дата
его последней модификации.
(+26) 2 Номер первого кластера, распределенного файлу.
(+28) 4 Размер файла в байтах.
0 | Файл предназначен только для чтения, в этот файл нельзя писать и его нельзя стирать.
|
1 | Скрытый файл, этот файл не будет появляться в списке файлов, создаваемом командой операционной системы DIR.
|
2 | Системный файл. Этот бит обычно установлен в файлах, являющихся составной частью операционной системы.
|
3 | Данный дескриптор описывает метку диска. Для этого дескриптора поля имени файла и расширения имени файла должны рассматриваться как одно поле длиной 11 байт. Это поле содержит метку диска.
|
4 | Дескриптор описывает файл, являющийся подкаталогом данного каталога.
|
5 | Флаг архивации. Если этот бит установлен в 1, это означает, что данный файл не был выгружен утилитой архивации (например, программой BACKUP).
|
6-7 | Зарезервированы. |
| |
15 11 10 5 4 0
++
¦ Часы (0...23) ¦ Минуты (0...59) ¦ Секунды/2 (0...29) ¦
++
15 9 8 5 4 0
++
¦ Год (0...119) ¦ Месяц (1...12) ¦ День (1...31) ¦
++
- 1 drv_num
номер устройства (0 соответствует устройству А, 1 - В и т.д.)
(+1) 1 drv_numd
дополнительный номер устройства внутри драйвера
(+2) 2 sec_size
размер сектора в байтах
(+4) 1 clu_size
число, на единицу меньшее количества секторов в кластере
(+5) 1 clu_base
если содержимое этого поля не равно нулю, то для получения общего числа секторов в кластере надо возвести 2 в степень clu_base и получившееся число прибавить к clu_size
(+6) 2 boot_siz
количество зарезервированных секторов (boot-сектора, начало корневого каталога)
(+8) 1 fat_num
количество копий FAT
(+9) 2 max_dir
максимальное число дескрипторов файлов в корневом каталоге (т.е. максимальное число файлов, которое может содержать корневой каталог на этом устройстве)
(+11) 2 data_sec
номер первого сектора данных на диске (номер сектора, соответствующего кластеру номер 2)
(+13) 2 hi_clust
максимальное количество кластеров (равно увеличенному на 1 количеству кластеров данных)
(+15) 1 fat_size
количество секторов, занимаемых одной копией FAT
(+16) 2 root_sec
номер первого сектора корневого каталога
(+18) 4 drv_addr
FAR-адрес заголовка драйвера, обслуживающего данное устройство
(+22) 1 media
байт описания среды носителя данных
(+23) 1 acc_flag
флаг доступа, 0 означает, что к устройству был доступ
(+24) 4 next
адрес следующего блока DDCB, для последнего блока в поле смещения находится число FFFF
--------------- только для DOS 2.x -----------------
(+28) 2 dir_clu
номер начального кластера текущего каталога (0 для корневого каталога)
(+30) 64 dir_path
строка в формате ASCIIZ, содержащая путь к текущему каталогу
--------------- DOS 3.х ----------------------------
(+28) 2 reserv1
зарезервироано, обычно равно 0
(+30) 2 built
число FFFF в этом поле означает, что блок DDCB был построен
- 1 drv_num
номер устройства (0 соответствует устройству А, 1 - В и т.д.)
(+1) 1 drv_numd
дополнительный номер устройства внутри драйвера
(+2) 2 sec_size
размер сектора в байтах
(+4) 1 clu_size
число, на единицу меньшее количества секторов в кластере
(+5) 1 clu_base
если содержимое этого поля не равно нулю, то для получения общего числа секторов в кластере надо возвести 2 в степень clu_base и получившееся число прибавить к clu_size
(+6) 2 boot_siz
количество зарезервированных секторов (boot-сектора, начало корневого каталога)
(+8) 1 fat_num
количество копий FAT
(+9) 2 max_dir
максимальное число дескрипторов файлов в корневом каталоге (т.е. максимальное число файлов, которое может содержать корневой каталог на этом устройстве)
(+11) 2 data_sec
номер первого сектора данных на диске (номер сектора, соответствующего кластеру номер 2)
(+13) 2 hi_clust
максимальное количество кластеров (равно увеличенному на 1 количеству кластеров данных)
(+15) 1 fat_size
количество секторов, занимаемых одной копией FAT
(+16) 1 reserv1
зарезервировано
(+17) 2 root_sec
номер первого сектора корневого каталога
(+19) 4 drv_addr
FAR-адрес заголовка драйвера, обслуживающего данное устройство
(+23) 1 media
байт описания среды носителя данных
(+24) 1 acc_flag
флаг доступа, 0 означает, что к устройству был доступ
(+25) 4 next
адрес следующего блока DDCB, для последнего блока в поле смещения находится число FFFF
(+29) 2 reserv2
зарезервироано
(+31) 2 built
число FFFF в этом поле означает, что блок DDCB был построен
F000:FFF5 (8) - дата изготовления BIOS;
F000:FFFC (2) - не используется;
F000:FFFE (1) - код типа компьютера.
Программируемый контроллер прерываний 8259 (отечественный аналог
- КР1810ВН59А) предназначен для обработки до восьми приоритетных
уровней прерываний. Возможно каскадирование микросхем, при этом
общее число уровней прерываний будет достигать 64.
Контроллер 8259 имеет несколько режимов работы, которые устанавливаются
программным путем. В персональных компьютерах XT и AT за первоначальную
установку режимов работы микросхем 8259 отвечает BIOSBIOS.
У программиста скорее всего не возникнет потребность перепрограммировать
контроллер - это небезопасно, так как неправильное программирование
контроллера приведет к нарушению логики работы всей системы.
Однако часто возникает необходимость изменения текущего режима
работы (запрет или разрешение прерываний определенного или всех
уровней, обработка конца прерывания) или опроса состояния внутренних
регистров контроллера. Для этого необходимо ознакомиться со справочными
данными на микросхему 8259, где детально описано как первоначальное
прогрммирование контроллера, так и управление им во время работы.
Каждому приоритетному уровню прерывания микросхема ставит в соответствие
определенный, задаваемый программно номер прерывания. В разделе
книги, посвященном особенностям обработки аппаратных прерываний,
приводится такое соответствие для машин типа XT и AT.
Если контроллеры 8259 каскадированы, то ведомой микросхеме присваивается
код (выдачей в микросхему соответствующего командного слова).
Этот код равен номеру входа IRQ ведущей микросхемы, с которым
соединен выход запроса прерывания INT ведомой микросхемы.
Внутри микросхемы приоритет зависит от номера IRQ и задается
программно. Для компьютеров XT и AT самым высоким приоритетом
внутри группы, обслуживаемой каждым контроллером, является вход
IRQ0. Однако возможно программное изменение приоритетов
в рамках так называемого приоритетного кольца. При этом дно приоритетного
кольца имеет самый низкий приоритет.
Приведем возможные варианты задания приоритетов:
Вход | Уровни приоритета
|
IRQ0 | 7 6 5 4 3 2 1 0
|
IRQ1 | 0 7 6 5 4 3 2 1
|
IRQ2 | 1 0 7 6 5 4 3 2
|
IRQ3 | 2 1 0 7 6 5 4 3
|
IRQ4 | 3 2 1 0 7 6 5 4
|
IRQ5 | 4 3 2 1 0 7 6 5
|
IRQ6 | 5 4 3 2 1 0 7 6
|
IRQ7 | 6 5 4 3 2 1 0 7
|
Наиболее высокий приоритет у входа IRQ с обозначением 0
приоритетного кольца, наиболее низкий - с обозначением 7.
Для обработки прерываний контроллер имеет несколько внутренних
регистров. Это регистр запросов прерываний IRR, регистр
обслуживания прерываний ISR, регистр маски прерываний IMR.
В регистре IRR хранятся запросы на обслуживание прерываний
от аппаратуры. После выработки сигнала прерывания центральному
процессору соответствующий разряд регистра ISR устанавливается
в единичное состояние, что блокирует обслуживание всех запросов
с равным или более низким приоритетом. Устранить эту блокировку
можно либо сбросом соответствующего бита в ISR, либо командой
специального маскирования.
Имеется два типа команд, посылемых программой в контроллер 8259
- команды инициализации и команды операции. Возможны следующие
операции:
- индивидуальное маскирование запросов прерывания;
- специальное маскирование обслуженных запросов;
- установка статуса уровней приоритета (по установке исходного
состояния, по обслуженному запросу, по указанию);
- операции конца прерывания (обычный конец прерывания, специальный
конец прерывания, автоматический конец прерывания);
- чтение регистров IRR, ISR, IMR.
Мы не будем подробно описывать команды инициализации контроллера
8259, так как программистам они скорее всего не понадобятся. Желающих
разобраться во всех тонкостях задания начального режима работы
контроллера прерываний мы отсылаем к справочной литературе по
микросхеме 8259 или ее отечественному аналогу.
Рассмотрим команды операций. Существуют три типа команд операций:
- Маскирование запросов прерывания.
- Команды обработки конца прерывания.
- Опрос регистров и специальное маскирование.
Байты команды маскирования запросов прерывания выводятся соответственно
в порты 21h и A1h для первого и второго контроллера
8259 компьютера AT. Команды операций второго и третьего типа используют
порты с адресами 20h и A0h.
Маскирование запросов прерываний мы уже описывали в главе, посвященной
прерываниям. Для маскирования какого-либо уровня прерывания надо
записать в регистр маски IMR по адресу 21h или A1h
единицу в соответствующий разряд регистра.
Команды обработки конца прерывания приведем в виде таблицы:
Биты байта команды
D7 D6 D5 D4 D3 D2 D1 D0
| Описание |
0 0 1 0 0 0 0 0 | Обычный конец прерывания.
|
0 1 1 0 0 B2 B1 B0 | Специальный конец прерывания, B0...B2 - двоично-десятичный код сбрасываемого разряда в регистре обслуживания прерывания ISR.
|
1 0 1 0 0 X X X | Циклический сдвиг уровней приоритета с обычным концом прерывания. Дно приоритетного кольца устанавливается по обслуженному запросу.
|
1 1 1 0 0 B2 B1 B0 | Циклический сдвиг уровней приоритета со специальным концом прерывания, B0...B2 - двоично-десятичный код дна приоритетного кольца.
|
1 0 0 0 0 X X X | Разрешение вращения уровней приоритета.
|
0 0 0 0 0 X X X | Сброс разрешения вращения уровней приоритета.
|
1 1 0 0 0 B2 B1 B0 | Циклический сдвиг уровней приоритета без завершения прерывания, B0...B2 - двоично-десятичный код дна приоритетного клоьца.
|
Команды третьего типа выдаются также в порты с адресами 20h
и A0h. Они имеют следующий формат:
Биты байта команды
D7 D6 D5 D4 D3 D2 D1 D0
| Описание |
0 0 0 0 1 1 X X | Установка режима опроса.
|
0 0 0 0 1 0 1 1 | Разрешение чтения регистра ISR.
|
0 0 0 0 1 0 1 0 | Разрешение чтения регистра IRR.
|
0 1 1 0 1 0 0 0 | Разрешение триггера специального маскирования.
|
0 1 0 0 1 0 0 0 | Сброс триггера специального маскирования.
|
По команде обычного конца прерывания устанавливается в нулевое
состояние разряд ISR, соответствующий последнему обслуженному
запросу.
Команда специального конца прерывания устанавливает в нулевое
состояние тот разряд ISR, номер которого указан в разрядах
B0...B2 команды.
Команда циклического сдвига уровней приоритета с обычным концом
прерывания устаналивает в ноль разряд ISR, соответствующий
последнему обслуженному запросу, и этому же номеру запроса присваивается
низший уровень приоритета.
Аналогично работает команда циклического сдвига уровней приоритета
со специальным концом прерывания, только низший уровень приоритета
присваивается тому входу IRQ, номер которого указан в разрядах
B0...B2 команды.
Команда циклического сдвига уровней приоритета устанавливает статус
уровней приоритета без выполнения операции конца прерывания. Разряды
B0...B2 указывают дно приоритетного кольца.
После выполнения команд разрешения чтения регистров ISR
или IRR при выполнении команды ввода из порта 20h
и A0h считывается соответственно содержимое регистров ISR
и IRR. Для получения содержимого регистра IMR необходимо
выполнить чтение портов с адресами соответственно 21h и
A1h.
Команда разрешения триггера специального маскирования блокирует
действие тех разрядов ISR, которые замаскированы командой
типа 1 (маскирования индивидуальных приоритетных уровней запроса
прерывания). Специальное маскирование используется для обслуживания
такого запроса, который блокируется старшим или равным по уровню
приоритета обслуженным запросом, хранящимся в ISR, не сбрасывая
последний.
Чтение регистров ISR и IRR может испльзоваться резидентными
программами при проверке возможности своей активизации - можно
проверить, не выполняется ли в настоящий момент обработка какого-нибудь
прерывания, которая может конфликтовать с действиями резидентной
программы.
Особенностью архитектуры процессоров INTEL 8086, 80286, 80386,
80486 является использование механизма сегментации адресного пространства.
Сегментация вызывает трудности у тех программистов, которые раньше
работали на ЭВМ типов PDP, СМ ЭВМ, ЕС ЭВМ. В этих машинах программа
имеет дело с логическими адресами, которые тем или иным способом
отображаются на физические адреса. Программа может не знать подробностей
отображения логических адресов на физические, она работает только
с логическим адресом.
Прообраз процессора 8086 - оригинальный микропроцессор INTEL 8080
- имел линейное адресное пространство размером 64 килобайта. В
этом микропроцессоре логический и физический адреса совпадали
- все 16 адресных линий (адресных шин) использовались непосредственно
для адресации памяти, а программы оперировали абсолютными шестнадцатиразрядными
адресами.
Однако быстро растущие потребности программ в оперативной памяти
привели к необходимости расширения адресного пространства. Следующий
микропроцессор 8086 имел уже 20 адресных линий, что позволило
непосредственно адресовать до мегабайта оперативной памяти. Архитектурное
решение этого микропроцессора позволило легко адаптировать накопленное
в большом количестве программное обеспечение для микропроцессора
8080.
Микропроцессор 8086 является шестнадцатиразрядным, поэтому использование
двадцатиразрядного адреса в 16-разрядных командах неэффективно.
Вместо указания в командах полного 20-разрядного адреса используется
двухкомпонентная адресация, причем каждая компонента использует
только 16 разрядов.
Эти компоненты называются сегментной компонентой адреса и компонентой
смещения. Логический 20-разрядный адрес получается сложением двух
компонент, причем сегментный адрес перед сложением умножается
на 16 (сдвигается влево на 4 разряда). Сложение и сдвиг выполняется
аппаратно, поэтому на формирование 20-разрядного адреса дополнительно
время не затрачивается.
На рисунке показано, как в процессоре 8086 происходит формирование
20-разрядного адреса из адреса сегмента и смещения:
19 4 3 0
+----------------------------------+
¦ Сегментный адрес ¦ 0 0 0 0 ¦
+----------------------------------+
+
19 16 15 0
+----------------------------------+
¦ 0 0 0 0 ¦ Смещение ¦
+----------------------------------+
=
19 0
+----------------------------------+
¦ Полный 20-разрядный адрес ¦
+----------------------------------+
Адрес сегмента сдвигается влево на 4 бита с заполнением младших
битов нулями, смещение расширяется до 20 битов и складывается
со сдвинутым адресом сегмента. Например, если адрес сегмента равен
1234h, а смещение равно 1116h, то полный 20-разрядный адрес будет
12340h + 01116h = 13456h.
Таким образом, оперируя 16-разрядными адресами сегмента и смещением,
процессор может адресовать мегабайт памяти. Для хранения сегментных
адресов и смещений процессор имеет специальные регистры.
Каждая выполняющаяся программа в любой момент времени может адресоваться
сразу к четырем сегментам памяти. Это сегмент кода, сегмент данных,
дополнительный сегмент данных, сегмент стека. Сегмент кода содержит
выполняющиеся машинные команды, сегменты данных и дополнительных
данных используются для размещения используемых программой переменных,
массивов и других структур данных, сегмент стека используется
при вызове подпрограмм.
Сегменты могут перекрываться или не перекрываться.
Для хранения сегментных адресов процессор имеет 4 сегментных регистра:
CS, DS, ES, SS. Эти регистры содержат соответственно адреса
сегментов кода, данных, дополнительных данных и стека.
При адресации выполняющегося кода вместе с регистром CS
используется регистр смещения IP. Пара регистров CS:IP
всегда указывает на текущую выполняющуюся команду.
Адресация данных возможна относительно любого сегментного регистра.
При этом смещение может указываться как непосредственно в команде,
так и с помощью регистров. Программа должна сама следить за правильной
загрузкой и использованием сегментных регистров.
Мы приведем несколько примеров программ, составленных на языке
ассемблера. Эти программы используют различное количество сегментов
и могут служить шаблоном для составления ваших собственных программ.
Первая программа использует всего один сегмент. В этом сегменте
расположены выполняющиеся машинные команды и данные, используемые
программой. Заметьте, что размер программы, состоящей из одного
сегмента, не может превышать 64 килобайта.
Текст программы:
; В этом месте расположен сегмент кода. Он содержит
; выполняющуюся программу.
code segment
; Директива assume сообщает ассемблеру, как будут
; использоваться сегментные регистры. Эта директива
; не выполняет загрузку сегментных регистров, она
; нужна ассемблеру только для правильного вычисления
; смещений.
assume cs:code, ds:code
; Эта строка нужна для создания com-программы.
org 100h
; При запуске программы управление будет передано
; на оператор с меткой start.
; Первое, что должна сделать программа - правильно
; загрузить сегментные регистры.
; Регистр CS загружается операционной системой
; при запуске программы, поэтому его загружать не надо.
; Регистры DS и ES должны указывать на начало
; сегмента кода, так как программа состоит из одного
; сегмента.
start:
mov ax, cs
mov ds, ax
; Выводим сообщение msg из сегмента данных
mov ah, 9h
mov dx, OFFSET msg
int 21h
; Завершаем работу программы
mov ax, 4C00h
int 21h
; Строка, которую программа выведет на экран.
msg db "Hello, world.", 13, 10, "$"
code ends
end start
Если для размещения данных и буферов недостаточно одного сегмента,
необходимо организовать отдельные сегменты для кода и данных,
как это сделано в следующем примере:
; Создаем сегмент стека. Размер стека - 256 байт,
; стек выравнен на границу параграфа (para).
stack segment para stack
; Резервируем 256 байт для стека.
db 100h dup (?)
stack ends
; Создаем сегмент данных. Этот сегмент выравнен на
; границу двухбайтового слова (word).
data segment word
; Строка, которую программа выведет на экран.
msg db "Hello, world.", 13, 10, "$"
data ends
; В этом месте расположен сегмент кода. Он содержит
; выполняющуюся программу.
code segment
; Директива assume сообщает ассемблеру, как будут
; использоваться сегментные регистры. Эта директива
; не выполняет загрузку сегментных регистров, она
; нужна ассемблеру только для правильного вычисления
; смещений.
assume cs:code, ds:data, ss:stack
; При запуске программы управление будет передано
; на оператор с меткой start.
; Первое, что должна сделать программа - правильно
; загрузить сегментные регистры.
;
; Следующие два оператора инициализируют сегментный
; регистр данных DS.
start:
mov ax, data
mov ds, ax
; Инициализируем сегментный регистр стека и
; указатель стека (регистры SS и SP).
; Эта операция должна выполняться в состоянии
; процессора с запрещенными прерываниями, иначе
; если регистр SS будет содержать уже новое значение,
; а SP - старое и если в этот момент произойдет
; прерывание, адрес возврата и значение регистра флагов
; будут записаны в не предназначенную для этого область.
cli
mov ss, ax
mov sp, OFFSET stack
sti
; Выводим сообщение msg из сегмента данных
mov ah, 9h
mov dx, OFFSET msg
int 21h
; Завершаем работу программы
mov ax, 4C00h
int 21h
code ends
end start
Макроассемблер MASM версии 5.0 и более поздних версий, а также
Quick Assembler содержит директивы, упрощающие описание сегментов.
Это такие директивы, как .CODE, .DATA, .MODEL и другие.
Вы найдете подробное описание этих директив в соответствующей
документации по ассемблеру. Остановимся подробнее на директиве
.MODEL.
Эта директива задает так называемую модель памяти, используемую
программой. Что это такое?
Мы уже говорили о том, что программа должна состоять из одного
или нескольких сегментов, в зависимости от размера кода и данных,
которыми она оперирует. Существует несколько стандартных вариантов
использования сегментов, которые называются моделями памяти. Всего
используются шесть моделей памяти:
- Tiny;
- Small;
- Medium;
- Compact;
- Large;
- Huge.
Модель памяти Tiny используется небольшими программами,
состоящими из одного сегмента и имеющими формат COM. Использование
этой модели памяти - единственный способ получения загрузочного
модуля в формате COM.
В модели Small один сегмент используется для кода, один
для хранения данных и размещения стека программы. Общий размер
программы в этом случае ограничен величиной 128 килобайтов. Большинство
небольших программ используют именно эту модель памяти.
Если ваша программа оперирует небольшим объемом данных, но размер
кода превышает 64 килобайта, вам подходит модель Medium.
В этой модели используется несколько сегментов для хранения кода
и только один - для данных.
Модель Compact, в отличие от Medium, использует
один сегмент для кода и несколько - для данных. Эта модель больше
всего подходит для небольших программ, обрабатывающих большие
массивы данных.
Модель памяти Large предоставляет возможность использовать
несколько сегментов для кода и несколько сегментов для данных.
Эта модель обычно используется большими программами, которые обрабатывают
большие объемы данных.
И, наконец, модель памяти Huge. Эта модель аналогична Large,
но для программ, составленных на языке Си, она позволяет использовать
массивы данных, имеющие размер более одного сегмента.
Приведем два примера использования моделей памяти в программах,
составленных на языке ассемблера. Эти примеры аналогичны тем,
которые мы только что рассмотрели. Первая программа использует
модель памяти Tiny:
; Определяем используемую модель памяти
.model tiny
; Определяем сегмент данных.
.data
msg db "Hello, world.", 13, 10, "$"
; Определяем сегмент кода.
.code
; Макрокоманда startup выполняет все необходимые
; инициализирующие действия, которые зависят от
; модели памяти.
.startup
; Выводим сообщение на экран
mov ah, 9h
mov dx, OFFSET msg
int 21h
; Завершаем выполнение программы
.exit
END
Вторая программа использует модель памяти Small, в ней
мы дополнительно определили свой стек:
; Определяем используемую модель памяти
.model small
; Определяем сегмент данных.
.data
msg db "Hello, world.", 13, 10, "$"
; Определяем свой стек, его размер - 256 байтов
.stack 100h
; Определяем сегмент кода.
.code
.startup
; Выводим сообщение на экран
mov ah, 9h
mov dx, OFFSET msg
int 21h
; Завершаем выполнение программы
.exit
END
Для программ, составленных на языке Си, модель памяти указывается
при трансляции. Если используется пакетный транслятор, модель
указывается при помощи опций в командной строке. Если вы работаете
в интегрированной среде, такой как Quick C, модель задается при
помощи соответствующего меню, а сама программа не содержит каких-либо
директив, определяющих используемую модель памяти.
Как правильно выбрать модель памяти?
Если ваша программа небольшая по размеру, то вам подойдут модели
TINY или SMALL. При использовании остальных моделей
памяти возможно увеличение размера загрузочного модуля и времени
выполнения программы из-за того, что в операциях с данными и при
вызове подпрограмм используются полные адреса, состоящие из сегмента
и смещения. Это означает, в частности, что если при трансляции
программы была использована модель LARGE, то при обращении
к каждой переменной и при вызове каждой подпрограммы (функции)
будет использоваться полный адрес.
Для сокращения накладных расходов отдельные переменные и функции
можно разместить в отдельном сегменте. Для этого их надо описать
специальным образом - используя ключевое слово near (для С 6.0
и QC 2.5 можно использовать _near).
Ключевое слово near (_near) сообщает транслятору,
что данные должны быть размещены в некотором общем сегменте данных
и доступ к ним должен осуществляться с использованием 16-битового
адреса (только компонента смещения). Если с этим ключевым словом
описана функция, то транслятор поместит ее в текущий сегмент кода,
для вызова функции будет также использован 16-битовый адрес.
В противоположность к только что описанному ключевое слово far
(_far для С 6.0 и QC 2.5) говорит о том, что данные или
функция могут располагаться в любом месте памяти, не обязательно
в текущем сегменте, и для адресации необходимо использовать полный
32-битовый адрес.
Ключевое слово huge (_huge) необходимо использовать
при описании массвов, которые по своим размерам могут превышать
64К. Для адресации при этом будет использоваться полный 32-битовый
адрес. Для функций это ключевое слово не применяется.
Приведем несколько примеров описания данных и функций с использованием
ключевых слов near, far, huge.
// Используемая модель памяти - SMALL
char dim1[250];
char _far dim2[45000];
char _huge dim3[80000];
char _far *far_ptr;
char _far * _far * far_ptr1;
int _far function1(void);
// Используемая модель памяти - LARGE
char _near dim4[2000];
char _far * _near function2(void);
Исчерпывающие сведения об использовании моделей памяти можно почерпнуть
из документации на используемый транслятор.
/* SYSP.H - include-файл для примеров, приведенных в книге */
/**
*.Name FP_MAKE
*
*.Title Макро для составления FAR-указателя
*
*.Descr Макро составляет FAR-указатель, пользуясь
* значениями сегмента и смещения
*
*.Params FP_MAKE(seg,off)
* seg - сегмент;
* off - смещение
*
*.Return FAR-указатель seg:off
**/
#define FP_MAKE(seg,off) ((void far *)
((((unsigned long) (unsigned)(seg)) << 16L) |
((unsigned long) (unsigned) (off))))
/* Структура векторной таблицы связи DOS */
#pragma pack(1)
typedef struct _CVT_ {
unsigned mcb_seg;
void far *dev_cb;
void far *file_tab;
void far *clock_dr;
void far *con_dr;
unsigned max_btbl;
void far *disk_buf;
void far *drv_info;
void far *fcb_tabl;
unsigned fcb_size;
unsigned char num_bdev;
unsigned char lastdriv;
} CVT;
/* Блок управления памятью MCB */
typedef struct _MCB_ {
unsigned char type;
unsigned owner;
unsigned size;
char reserve[11];
} MCB;
/* Префикс программного сегмента PSP */
typedef struct _PSP_ {
unsigned char int20h[2];
unsigned mem_top;
unsigned char reserv1;
unsigned char call_dsp[5];
void far *term_adr;
void far *cbrk_adr;
void far *crit_err;
unsigned parn_psp;
unsigned char file_tab[20];
unsigned env_seg;
void far *ss_sp;
unsigned max_open;
void far *file_tba;
unsigned char reserv2[24];
unsigned char disp[3];
unsigned char reserv3[9];
unsigned char fcb1[16];
unsigned char fcb2[20];
unsigned char p_size;
unsigned char parm[127];
} PSP;
/* Блок управления устройством DOS */
typedef struct _DDCB_ {
unsigned char drv_num;
unsigned char drv_numd;
unsigned sec_size;
unsigned char clu_size;
unsigned char clu_base;
unsigned boot_siz;
unsigned char fat_num;
unsigned max_dir;
unsigned data_sec;
unsigned hi_clust;
unsigned char fat_size;
char reserv1;
unsigned root_sec;
void far *drv_addr;
unsigned char media;
unsigned char acc_flag;
struct _DDCB_ far *next;
unsigned reserv2;
unsigned built;
} DDCB;
/* Управляющий блок DOS для файлов */
typedef struct _DFCB_ {
unsigned handl_num;
unsigned char access_mode;
unsigned reserv1;
unsigned dev_info;
void far *driver;
unsigned first_clu;
unsigned time;
unsigned date;
unsigned long fl_size;
unsigned long offset;
unsigned reserv2;
unsigned reserv7;
unsigned reserv3;
char reserv4;
char filename[11];
char reserv5[6];
unsigned ownr_psp;
unsigned reserv6;
unsigned last_clu;
char reserv8[4];
} DFCB;
/* Таблица файлов DOS */
typedef struct _DFT_ {
struct _DFT_ far *next;
unsigned file_count;
DFCB dfcb;
} DFT;
/* Управляющий блок дискового буфера BCB */
typedef struct _BCB_ {
struct _BCB_ far *next;
unsigned char drive;
unsigned char flag;
unsigned sect_num;
unsigned reserv1;
DDCB far *ddcb;
unsigned reserv2;
} BCB;
/* Информация о диске */
typedef struct _DINFO_ {
char path[64];
unsigned reserv1;
unsigned reserv2;
unsigned char reserv3;
DDCB far *ddcb;
unsigned cdir_clu;
unsigned reserv4;
unsigned reserv5;
unsigned reserv6;
unsigned char reserv7[7];
} DINFO;
/* Заголовок EXE-программы */
typedef struct _EXE_HDR_ {
unsigned signature;
unsigned part_pag;
unsigned file_size;
unsigned rel_item;
unsigned hdr_size;
unsigned min_mem;
unsigned max_mem;
unsigned ss_reg;
unsigned sp_reg;
unsigned chk_summ;
unsigned ip_reg;
unsigned cs_reg;
unsigned relt_off;
unsigned overlay;
} EXE_HDR;
/* таблица расположения сегментов EXE-программы */
typedef struct _RELOC_TAB_ {
unsigned offset;
unsigned segment;
} RELOC_TAB;
/* конфигурация дисковой подсистемы */
typedef struct _DISK_CONFIG_ {
int n_floppy;
int n_hard;
int t_floppy1;
int t_floppy2;
int t_hard1;
int t_hard2;
} DISK_CONFIG;
/* таблица параметров дискеты */
typedef struct _DPT_ {
unsigned char srt_hut;
unsigned char dma_hlt;
unsigned char motor_w;
unsigned char sec_size;
unsigned char eot;
unsigned char gap_rw;
unsigned char dtl;
unsigned char gap_f;
unsigned char fill_char;
unsigned char hst;
unsigned char mot_start;
} DPT;
/* таблица параметров диска */
typedef struct _HDPT_ {
unsigned max_cyl;
unsigned char max_head;
unsigned srwcc;
unsigned swpc;
unsigned char max_ecc;
unsigned char dstopt;
unsigned char st_del;
unsigned char fm_del;
unsigned char chk_del;
unsigned char reserve[4];
} HDPT;
/* Элемент таблицы разделов */
typedef struct _PART_ENTRY_ {
unsigned char flag;
unsigned char beg_head;
unsigned beg_sec_cyl;
unsigned char sys;
unsigned char end_head;
unsigned end_sec_cyl;
unsigned long rel_sec;
unsigned long size;
} PART_ENTRY;
/* Главная загрузочная запись */
typedef struct _MBOOT_ {
char boot_prg[0x1be];
PART_ENTRY part_table[4];
unsigned char signature[2];
} MBOOT;
/* Расширенный блок параметров BIOS */
typedef struct _EBPB_ {
unsigned sectsize;
char clustsize;
unsigned ressecs;
char fatcnt;
unsigned rootsize;
unsigned totsecs;
char media;
unsigned fatsize;
unsigned seccnt;
unsigned headcnt;
unsigned hiddensec_low;
unsigned hiddensec_hi;
unsigned long drvsecs;
} EBPB;
/* Загрузочная запись для MS-DOS 4.01 */
typedef struct _BOOT_ {
char jmp[3];
char oem[8];
EBPB bpb;
char drive;
char reserved;
char signature;
unsigned volser_lo;
unsigned volser_hi;
char label[11];
char fat_format[8];
char boot_code[450];
} BOOT;
/* Время последнего обновления файла */
typedef struct _FTIME_ {
unsigned sec : 5, min : 6, hour : 5;
} FTIME;
/* Дата последнего обновления файла */
typedef struct _FDATE_ {
unsigned day : 5, month : 4, year : 7;
} FDATE;
/* Дескриптор файла в каталоге */
typedef struct _FITEM_ {
char name[8];
char ext[3];
char attr;
char reserved[10];
FTIME time;
FDATE date;
unsigned cluster_nu;
unsigned long size;
} FITEM;
/* Формат дорожки для GENERIC IOCTL */
typedef struct _TRK_LY_ {
unsigned no;
unsigned size;
} TRK_LY;
/* Параметры устройства для GENERIC IOCTL */
typedef struct _DPB_ {
char spec;
char devtype;
unsigned devattr;
unsigned numofcyl;
char media_type;
EBPB bpb;
char reserved[6];
unsigned trkcnt;
TRK_LY trk[100];
} DPB;
/* Параметры для форматирования функцией GENERIC IOCTL */
typedef struct _DPB_FORMAT_ {
char spec;
unsigned head;
unsigned track;
} DPB_FORMAT;
/* Параметры для чтения/записи функцией GENERIC IOCTL */
typedef struct _DPB_WR_ {
char spec;
unsigned head;
unsigned track;
unsigned sector;
unsigned sectcnt;
void _far *buffer;
} DPB_WR;
/* Идентификатор BIOS */
typedef struct _BIOS_ID_ {
char date[8];
unsigned reserve;
char pc_type;
} BIOS_ID;
#pragma pack()
void far *get_cvt(void); /* получить адрес векторной таблицы связи */
CVT far *get_mcvt(void); /* получить адрес векторной таблицы связи */
MCB far *get_fmcb(CVT far *); /* получить адрес первого MCB */
MCB far *get_nmcb(MCB far *); /* получить адрес следующего MCB */
DDCB far *get_fddcb(CVT far *); /* получить адрес первого DDCB */
DDCB far *get_nddcb(DDCB far *); /* получить адрес следующего DDCB */
DDCB far *get_ddcb(unsigned char); /* получить адрес DDCB для диска */
DFT far *get_fdft(CVT far *); /* получить адрес первой DFT */
DFT far *get_ndft(DFT far *); /* получить адрес следующей DFT */
BCB far *get_fbcb(CVT far *); /* получить адрес первого BCB */
BCB far *get_nbcb(BCB far *); /* получить адрес следующего BCB */
int get_exeh(EXE_HDR *,RELOC_TAB **, FILE *); /* прочитать заголовок EXE */
char unsigned pc_model(void); /* получить модель компьютера */
void disk_cfg(DISK_CONFIG*); /* определить конфигурацию
дисковой подсистемы */
DPT _far *get_dpt(void); /* получить адрес DPT */
HDPT _far *get_hdp1(void); /* получить адрес первой HDPT */
HDPT _far *get_hdp2(void); /* получить адрес второй HDPT */
BIOS_ID _far *getbiosi(void); /* получить адрес идентификатора BIOS */
;
; Это макроопределение печатает символы на экране
;
@@out_ch MACRO c1,c2,c3,c4,c5,c6,c7,c8,c9,c10
mov ah,02h
IRP chr,<c1,c2,c3,c4,c5,c6,c7,c8,c9,c10>
IFB <chr>
EXITM
ENDIF
mov dl,chr
int 21h
ENDM
ENDM
@@out_str MACRO
mov ah,9
int 21h
ENDM
7.6.1. Новое в MS-DOS версии 5.0
7.6.2. Изменения в векторной таблице связи
7.6.3. Управление памятью
7.6.4. Управление программами
7.6.5. Резидентные программы
7.6.6. Драйверы
7.6.7. Переключатель задач
Версия 5.0 операционной системы MS-DOS не разочаровала пользователей
компьютеров и программистов. Преимущества столь значительны и
заметны, что уже не может быть оправдания для приверженцев версии
3.30 или даже 4.01. Перечислим только основные нововведения.
- Возможность загрузки ядра DOS в так называемую верхнюю память.
Эта память расположена за пределами первого мегабайта оперативной
памяти, что позволяет выделить для программ пользователя до 630
(!) килобайт свободного пространства.
- При работе MS-DOS версии 5.0 на компьютере, оснащенном процессором
80386 или 80486 возможна выгрузка драйверов и резидентных
программ в расширенную память. Для этого можно использовать драйвер
EMM386.
- Новая диалоговая оболочка DOSSHELL обеспечивает переключение
задач. Это еще не мультизадачность, так как все запущенные программы,
кроме одной, приостанавливают свою работу и выгружаются на диск.
В любой момент времени работает только одна программа, остальные
ждут своей очереди на диске. Возможности переключателя задач будут
рассмотрены в разделе "Переключатель задач".
- Многие функции и прерывания MS-DOS, которые были недокументированы
в предыдущих версиях, получили "признание", отныне программисты
могут использовать их на законных основаниях. Особенно это относится
к функциям, обеспечивающим работу резидентных программ.
- Появились новые функции и новые возможности для программистов.
Мы кратко рассмотрим наиболее полезные, на наш взгляд, новые функции
MS-DOS в следующих разделах этой главы.
Сразу отметим, что функция 30h прерывания INT 21h,
возвращающая версию MS-DOS, может ввести вас в заблуждение.
Возможно, вы будете сильно удивлены, когда в среде MS-DOS версии
5.0 эта функция сообщит о том, что у вас MS-DOS версии 3.30 или
даже 1.0. Как это может быть?
В состав MS-DOS версии 5.0 входит драйвер SETVER.EXE. Этот
драйвер поддерживает список имен программ, в котором каждому имени
поставлен в соответствие номер версии MS-DOS, возвращаемый функцией
30h.
При запуске программы драйвер SETVER.EXE сверяет ее имя
со списком (который, кстати, вы можете редактировать) и модифицирует
соответствующим образом обработчик функции 30h.
Для чего потребовалось вводить программы в заблуждение относительно
используемой версии MS-DOS?
Дело в том, что некоторые программы (а также драйверы) рассчитаны
на работу только в среде конкретной версии MS-DOS, например, 4.00
или 4.01. На самом деле эти программы будут правильно работать
и в MS-DOS версии 5.0. Но проверив версию, такие программы часто
завершают свое выполнение с сообщением об ошибке в номере версии.
Вы можете получить список таких программ, просто запустив SETVER.EXE
как обычную программу.
Как же получить "правильный" номер версии MS-DOS?
Для этого необходимо использовать функцию 3306h прерывания
INT 21h.
Приведем формат этой функции.
Регистры на входе:
Регистр | Содержимое
|
AX | 3306h |
Регистры на выходе:
Регистр | Содержимое
|
BH | Верхний (major) номер версии.
|
BL | Нижний (minor) номер версии.
|
DL | Биты 0..2 содержат номер изменения (revision), остальные биты равны 0.
|
DH | Флаги:
Бит 3 - DOS находится в ПЗУ;
Бит 4 - DOS загружен в старшие
адреса памяти (область HMA)
|
Функция 30h в версии MS-DOS также претерпела некоторые
изменения. Если при вызове этой функции в регистр AL записать
значение 00h, все будет аналогично версиям 2.0-4.0. Если
в AL записать 01h, после возврата регистр BH
будет содержать флаги, по которым можно судить о расположении
MS-DOS в ПЗУ или в старших адресах памяти.
Приведем полный формат вызова функции 30h прерывания INT 21h.
Регистры на входе:
Регистр | Содержимое
|
AH | 30h |
AL | 00h - получить код ОЕМ (код фирмы-изготовителя DOS) и версию DOS;
01h - получить флаги расположения DOS.
|
Регистры на выходе:
Регистр | Содержимое
|
AL | Верхний (major) номер версии.
|
AH | Нижний (minor) номер версии.
|
BX:CL | 24-битовый серийный номер конкретного экземпляра MS-DOS
|
BH | Если при вызове функции AL был равен 0:
Код фирмы-изготовителя:
00h - IBM;
05h - Zenith;
16h - DEC;
23h - Olivetti;
29h - Toshiba;
4Dh - Hewlett Packard;
99h - архитектура STARLITE;
FFh - Microsoft, Phoenix.
Если при вызове функции AL был равен 1:
08h - DOS расположен в ПЗУ;
10h - DOS загружен в старшие адреса памяти (область HMA).
|
Формат векторной таблицы связи для MS-DOS версии 5.0 практически
идентичен используемому версией 4.0. В этой таблице добавился
указатель на список программ, для которых драйвер SETVER.EXE
выполняет подстановку значения версии MS-DOS.
Приведем формат векторной таблицы связи для MS-DOS версии 5.0:
(-02h) 2 | mcb_seg
| сегмент первого управляющего блока памяти (MCB)
|
(00h) 4 | dev_cb
| указатель на первый блок управления устройствами DOS (DOS Device Control Block)
|
(+04h) 4 | file_tab
| указатель на таблицу файлов DOS |
(+08h) 4 | clock_dr
| указатель на драйвер CLOCK$, установленный или резидентный
|
(+0Ch) 4 | con_dr
| указатель на актуальный драйвер CON, установленный или резидентный
|
(+10h) 2 | max_btbl
| максимальное число байт в блоке блочного устройства
|
(+12h) 4 | disk_buf
| указатель на структуру, описывающую дисковые буфера
|
(+16h) 4 | drv_info
| укзатель на массив информации об устройствах
|
(+1Ah) 4 | fcb_tabl
| указатель на таблицу FCB |
(+1Eh) 2 | fcb_size
| размер таблицы FCB, для версии MS-DOS 5.0 в этом поле находится значение 00h
|
(+20h) 1 | num_bdev
| число блочных устройств |
(+21h) 1 | lastdriv
| значение LASTDRIVE в файле CONFIG.SYS (по умолчанию равно 5)
|
(+22h) 18 | null_dr
| заголовок драйвера NUL - первого драйвера в списке драйверов DOS
|
(+34h) 1 | joined
| количество устройств, подсоединенных при помощи команды JOIN
|
(+35h) 2 | special_prg
| смещение внутри сегмента кода IBMDOS списка специальных программ, для MS-DOS 5.0 в этом поле находится 0000h
|
(+ 37h) 4 | setver_list
| указатель на список программ, для которых драйвер SETVER.EXE выполняет подстановку значения версии MS-DOS
|
(+3Bh) 4 | internal_1
| используется MS-DOS |
(+3Fh) 2 | buffers_x
| значение x в команде BUFFERS x,y |
(+41h) 2 | buffers_y
| значение y в команде BUFFERS x,y |
(+43h) 1 | boot_drive
| номер дискового устройства, использованного для загрузки MS-DOS (1 - A:)
|
(+44h) 1 | cpu_type
| 01h, если используется процессор 80386 или 80486, 00h для 8086 - 80286.
|
(+45h) 2 | extended_mem
| размер установленной расширенной памяти в килобайтах
|
В MS-DOS версии 5.0 стал документирован блок управления памятью
MCB. Приведем формат этого блока.
(00h) 1 | Тип блока: 4Dh для всех блоков, кроме последнего. Для последнего блока используется значение 5Ah.
|
(01h) 2 | Сегментный адрес блока PSP программы-владельца данного MCB или значение 0008h для MCB, принадлежащего MS-DOS. Для свободного блока MCB в этом поле находится значение 0000h.
|
(03h) 2 | Размер блока MCB в параграфах.
|
(05h) 3 | Не используются.
|
(08h) 8 | ASCII-имя программы-владельца блока MCB, если это блок PSP.
|
Самый первый блок MCB является сегментом данных MS-DOS.
Он делится на подсегменты, в которых расположены драйверы, системные
данные, буфера и т.д.
Приведем формат управляющего блока подсегмента для первого блока
MCB. Этот управляющий блок расположен непосредственно перед
соотвестсвующим ему подсегментом.
(00h) 1 | Тип подсегмента:
"D" - драйвер устройства;
"E" - расширение драйвера устройства;
"I" - драйвер инсталлируемой файловой системы IFS;
"F" - область памяти для управляющего блока оператора "FILES=";
"X" - область памяти для управляющего блока оператора "FCBS=";
"C" - рабочая область для буферов EMS, если используется оператор "BUFFERS /X";
"B" - рабочая область для буферов, если используется оператор "BUFFERS";
"L" - область памяти для массива структур текущих каталогов;
"S" - сегмент памяти для оператора "STACKS=";
"T" - сегмент памяти для оператора "INSTALL=".
|
(01h) 2 | Параграф, начиная с которого располагается данный подсегмент. Обычно это следующий за управляющим блоком параграф.
|
(03h) 2 | Размер подсегмента в параграфах.
|
(05h) 3 | Не используются.
|
(08h) 8 | Для подсегментов "I" и "D" в этом поле находится имя файла, из которого был загружен драйвер.
|
Кроме рассмотренных выше, в MS-DOS версии 5.0 появился новый тип
управляющего блока памяти - UMCB - управляющий блок для
верхней области памяти UMB (Upper Memory Block):
(00h) 1 | Тип блока: 4Dh для всех блоков, кроме последнего. Для последнего блока используется значение 5Ah.
|
(01h) 2 | Первый доступный в верхней памяти UMB параграф для самого первого блока UMCB, 000Ah - если управляющий блок расположен в конце UMB.
|
(03h) 2 | Размер блока UMB в параграфах.
|
(05h) 3 | Не используются.
|
(08h) 8 | Тип блока: "UMB" для начального блока, "SM" - для конечного.
|
Начиная с версии 3.0 MS-DOS содержит функцию 58h прерывания
INT 21h, позволяющую определять и изменять стратегию
выделения памяти запущенным программам. В версии 5.0 добавились
новые возможности, в частности, возможность выделения блоков верхней
памяти, используемых только в MS-DOS версии 5.0.
Регистры на входе:
Регистр | Содержимое
|
AH | 58h |
AL | Подфункция:
00h - определить используемую стратегию;
01h - установить стратегию;
02h - получить состояние списка блоков верхней памяти UMB;
03h - установить состояние списка блоков верхней памяти UMB.
|
BL | Подфункция 01h - новая стратегия:
00h - первым заполняется первый свободный участок в области младших адресов памяти;
01h - аналогично, но используется участок памяти, наилучшим образом подходящий для запроса;
02h - аналогично, но используется последний свободный участок памяти;
40h ,41h 42h - аналогично 00h, 01h, 02h, но используются старшие адреса памяти;
80h, 81h, 82h - аналогично 00h, 01h, 02h, но сначала делается попытка выделить старшие адреса памяти, а в случае неудачи - младшие.
Подфункция 03h - новое состояние списка блоков верхней памяти:
BX = 0000h - удалить блоки UMB из списка блоков памяти DOS;
BX = 0001h - добавить блоки UMB в список блоков памяти DOS.
|
BH | Подфункция 01h - новая стратегия:
Равен 00h.
|
Регистры на выходе:
Регистр | Содержимое
|
AX | Подфункция 00h - определить стратегию:
AX = код используемой стратегии (см. выше).
Подфункция 02h - определитьсостояние списка блоков верхней памяти:
AL = 00h - блоки UMB удалены из списка блоков памяти DOS;
AL = 01h - блоки UMB входят в список блоков памяти DOS.
|
В версии 5.0 MS-DOS появились функция для непосредственного выделения
программам блоков старшей памяти HMA. Это
функция 4A02h:
Регистры на входе:
Регистр | Содержимое
|
AX | 4A02h |
BX | Размер выделяемого блока памяти в байтах (после возврата содержимое этого регистра будет уничтожено).
|
Регистры на выходе:
Регистр | Содержимое
|
ES:DI | Адрес выделенного блока памяти или FFFF:FFFF в случае неудачи.
|
Прежде чем пользоваться только что описанной функцией, имеет смысл
определить размер свободной старшей памяти при помощи функции
4A01h:
Регистры на входе:
Регистр | Содержимое
|
AX | 4A01h |
Регистры на выходе:
Регистр | Содержимое
|
BX | Размер доступной области старшей памяти в байтах или 0000h, если DOS не использует область HMA.
|
ES:DI | Адрес начала доступной области старшей памяти или FFFF:FFFF, если DOS не использует область HMA.
|
В версии 5.0 MS-DOS появились некоторые новые функции, имеющие
отношение к управлению программами. Например, функция 4B05h
прерывания INT 21h предназначена для подготовки программы
к выполнению. Эта функция может использоваться программами, перехватывающими
функцию 4B00h (обычный запуск программы), например, для
установки версии MS-DOS.
Регистры на входе:
Регистр | Содержимое
|
AX | 4B05h |
DS:DX | Адрес управляющей структуры (см. ниже)
|
Регистры на выходе:
Регистр | Содержимое
|
AX | 00h, если сброшен флаг CF и, соответственно, функция выполнилась без ошибок;
код ошибки, если установлен флаг CF.
|
Перед вызовом функции необходимо подготовить управляющую структуру:
(00h) 2 | Зарезервировано и равно 00h.
|
(02h) 2 | Флаги типа программы:
Бит 0 - программа типа .EXE;
Бит 1 - оверлей.
|
(04h) 4 | Указатель на ASCII-имя файла с программой.
|
(08h) 2 | PSP сегмента новой программы.
|
(0Ah) 4 | Стартовый адрес CS:IP новой программы.
|
(0Eh) 4 | Размер программы с учетом PSP.
|
После возврата из этой функции до завершения запущенной программы
нельзя вызывать прерывания DOS, BIOS или другие программные прерывания.
Если MS-DOS работает в верхней области памяти HMA, после
возврата из этой функции адресная линия A20 выключается
.
Некоторые недокументированные функции управления программами были
включены в документацию MS-DOS версии 5.0:
Функция | Назначение
|
50h | Установить PSP для текущей программы.
|
51h | Получить PSP текущей программы.
|
К сожалению, версия 5.0 операционной системы MS-DOS не порадовала
разработчиков какими-либо новыми возможностями в плане создания
резидентных программ. Это, в частности, говорит о неперспективности
данного класса программ. Очевидно, что при наличии переключателя
программ и таких средств, как Microsoft Windows, обеспечивающих
одновременное (или псевдо-одновременное) выполнение программ,
актуальность резидентных программ падает.
Но так как нельзя игнорировать большое количество уже созданных
(и достаточно удобных в использовании) резидентных программ, все
недокументированные ранее возможности, без которых невозможно
создать правильно работающую резидентную программу, стали документированными.
Взяв на себя обязательства поддерживать эти возможности, фирма
Microsoft гарантирует, что и в следующих версиях MS-DOS вы по-прежнему
сможете использовать свои старые добрые резидентные программы.
Что касается драйверов устройств, то версия 5.0 операционной системы
содержит расширения для работы с командами общего ввода/вывода
- GENERIC IOCTL.
В заголовке драйвера в слове атрибутов определен зарезервированный
ранее бит 7. Если этот бит установлен в 1, драйвер
поддерживает новую команду с кодом 19h. Эта команда позволяет
операционной системе определить, спосбен ли данный драйвер работать
с командами общего ввода/вывода (GENERIC IOCTL).
Для проверки возможности использования GENERIC IOCTL программа
может вызвать одну из двух новых функций - 4410h или 4411h.
Первая функция определяет поддержку GENERIC IOCTL для устройства,
заданного своим индексом (handle), вторая - для устройства,
заданного своим адресом (номером).
Функция 4410h:
Регистры на входе:
Регистр | Содержимое
|
AX | 4410h |
BX | Индекс (handle) устройства.
|
CH | Код категории:
00h неизвестное устройство
01h COMn:
03h CON
05h LPTn:
|
CL | Код функции, для которого необходимо выполнить проверку поддержки:
45h установить счетчик повторов
4Ah выбрать кодовую страницу
4Ch начать подготовку кодовой страницы
4Dh завершить подготовку кодовой страницы
5Fh установить информацию для отображения
65h получить счетчик повторов
6Ah запросить выбранную кодовую страницу
6Bh запросить подготовленный список
7Fh получить информацию для отображения
|
Регистры на выходе:
Регистр | Содержимое
|
AX | 0000h, флаг CF сброшен - данная функция GENERIC IOCTL поддерживается драйвером.
xx01h, флаг CF установлен в 1 - функция не поддерживается.
|
Функция 4411h:
Регистры на входе:
Регистр | Содержимое
|
AX | 4410h |
BL | Номер устройства.
|
CH | Код категории (08h - диск)
|
CL | Код функции, для которого необходимо выполнить проверку поддержки.
|
Регистры на выходе:
Регистр | Содержимое
|
AX | 0000h, флаг CF сброшен - данная функция GENERIC IOCTL поддерживается драйвером.
xx01h, флаг CF установлен в 1 - функция не поддерживается.
|
Переключатель задач, входящий в диалоговую оболочку DOSSHELL -
одно из значительных усовершенствований MS-DOS версии 5.0. Этото
переключатель позволяет запустить на выполнение одновременно несколько
программ, хотя в действительности работать будет только одна -
та, которая была запущена последней. Неактивные программы выгружаются
на диск.
Нажимая клавиши <ALT-TAB>, можно выбирать для выполнения
одну из запущенных программ.
Обратим ваше внимание на одну потенциальную опасность,
связанную с использованием переключателя задач.
Предположим, что одна из запущенных вами программ устанавливает
собственный обработчик какого-либо аппаратного прерывания. Например,
вы запустили телекоммуникационную программу и работаете через
модем с удаленным компьютером. Не исключено, что ваша программа
устанавливает собственный обработчик аппаратного прерывания от
асинхронного порта, к которому подключен модем.
Так как передача данных через модем - дело не быстрое, у вас может
появиться необходимость выполнить на компьютере какую-либо другую
работу, например, отредактировать и распечатать текст. Нет проблем,
вы переключаетесь на программу редактирования текстов. Но... компьютер
почему-то "зависает".
А дело оказывается в том, что выгрузив телекоммуникационную программу
на диск, переключатель задач "оторвал" обработчик аппаратного
прерывания асинхронного порта. Прерывание пришло, а обработчика-то
и нет!
Для пользователя в данной ситуации есть только один выход - не
использовать переключатель программ совместно с телекоммуникационными
программами.
Однако программист имеет возможность учесть в своих разработках
присутствие переключателя задач. Программа, определив наличие
переключателя, может либо отказаться от работы, либо запретить
переключение, если оно затребовано в неподходящий момент времени,
либо выполнить перед переключением некоторые "замораживающие"
действия (например, замаскировать аппаратное прерывание). Когда
программа вновь получит управление, она может "разморозиться".
Последний способ взаимодействия с переключателем самый удобный.
Он возможен благодаря тому, что переключатель задач имеет механизм,
позволяющий известить работающую программу о том, что затребовано
переключение.
|