Операционная система MS-DOS© Александр Фролов, Григорий ФроловТом 1, книги 1-2, М.: Диалог-МИФИ, 1991. 2.1. Таблица связи управляющих блоков MS-DOSОперационная система MS-DOS, подобно операционным системам для больших ЭВМ серии ЕС, содержит векторную таблицу связи основных управляющих блоков. К сожалению, в руководстве по MS-DOS ничего не говорится об этой таблице. Мы попытаемся в некоторой степени восполнить этот пробел, так как изучение векторной таблицы связи позволит глубже осознать принципы работы операционной системы. Информация из векторной таблицы связи будет полезной для составления программ отображения распределения памяти, вывода списка загруженных драйверов, списка устройств прямого доступа и т.д. Для получения адреса векторной таблицы связи можно воспользоваться недокументированной внутренней функцией 52h прерывания 21h. Для версий MS-DOS 2.х, 3.х, 4.00, 4.01 и 5.0 после вызова этой функции регистры ES:BX будут содержать искомый адрес. Так как описание этой функции отсутствует в руководстве по MS-DOS, в следующих версиях операционной системы возможно придется искать другой способ получения адреса векторной таблицы связи. Может также измениться формат этой таблицы. Функции для получения адреса векторной таблицы связи: ;** ;.Name get_cvt ; ;.Title Получить адрес векторной таблицы связи ; ;.Descr Функция возвращает адрес векторной таблицы связи ; в регистрах ES:BX для DOS версий 2.х, 3.х, 4.00, ; 4.01 ; ;.Params Нет ; ;.Return ES - сегмент векторной таблицы связи, ; BX - смещение векторной таблицы связи ;** PUBLIC get_cvt .MODEL tiny .CODE get_cvt proc near mov ax,5200h int 21h ret get_cvt endp end /** *.Name get_cvt * *.Title Получить адрес векторной таблицы связи * *.Descr Функция возвращает адрес векторной таблицы связи * для DOS версий 2.х, 3.х, 4.00, 4.01 * *.Params Нет * *.Return Указатель на векторную таблицу связи **/ #include <dos.h> #include <stdio.h> #include "sysp.h" void far *get_cvt(void) { union REGS inregs, outregs; struct SREGS segregs; inregs.h.ah = 0x52; intdosx( &inregs, &outregs, &segregs ); return(FP_MAKE(segregs.es,outregs.x.bx)); } В примере на языке Ассемблера процедура get_cvt вызывает функцию 52h прерывания 21h, после чего возвращает адрес векторной таблицы связи в регистрах ES:BX. Функция get_cvt, составленная на языке Си, также вызывает это прерывание, пользуясь функцией intdosx стандартной библиотеки транслятора. Функция intdosx вызывает прерывание 21h. В качестве параметров ей передаются адреса структур и объединения inregs, outregs и segregs. Объединение inregs должно содержать значения регистров перед вызовом прерывания, в объединение outregs и структуру segregs заносятся значения регистров общего назначения и сегментных регистров после того, как завершится обработка прерывания. Подробнее об этом сказано в описании стандартной библиотеки. Макро FP_MAKE описано в файле sysp.h и предназначено для конструирования FAR-указателя из значений сегмента и смещения: #define FP_MAKE(seg,off) ((void far *) \ ((((unsigned long) (unsigned)(seg)) << 16L) | \ ((unsigned long) (unsigned) (off)))) Следующая программа, составленная на языке Си, выводит на консоль адрес векторной таблицы связи: #include <stdio.h> #include "sysp.h" void main(void) { void far *cvt; cvt=get_cvt(); printf("Адрес векторной таблицы связи: %Fp\n",cvt); exit(0); } Спецификация формата вывода %Fp используется для вывода значения указателя типа FAR. Описание векторной таблицы связи, а также других управляющих блоков будет состоять из строк следующего вида: (+4) 4 filename_ptr - указатель на имя файла В этой строке: (+4) - смещение поля в управляющем поле в байтах; 4 - длина поля в байтах; filename - имя поля. Вслед за именем идет краткое описание содержимого поля. Итак, векторная таблица связи MS/DOS:
Функция get_cvt возвращает адрес поля dev_cb. Для удобства работы с векторной таблицей связи определим тип CVT: #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; #pragma pack() Эта структура содержит описание полей векторной таблицы связи для MS-DOS версий 3.х, 4.х и 5.0. Директива #pragma pack(1) предназначена для выравнивания полей структуры на границу байта. Эта директива необходима потому, что по умолчанию транслятор Microsoft выравнивает поля в структуре на границу 16-ти битового слова. Неправильное выравнивание может привести к тому, что поля структуры не будут располагаться в памяти последовательно. Заметьте, что функция get_cvt возвращает указатель на поле dev_cb. Модифицируем эту функцию так, чтобы можно было использовать для обращения к полям векторной таблицы связи структуру _CVT_: /** *.Name get_mcvt * *.Title Получить адрес векторной таблицы связи * *.Descr Функция возвращает адрес векторной таблицы связи * для DOS версий 2.х, 3.х, 4.00, 4.01 * *.Params Нет * *.Return Указатель на векторную таблицу связи **/ #include <dos.h> #include <stdio.h> #include "sysp.h" CVT far *get_mcvt(void) { union REGS inregs, outregs; struct SREGS segregs; inregs.h.ah = 0x52; intdosx( &inregs, &outregs, &segregs ); return((CVT far*)FP_MAKE(segregs.es,outregs.x.bx-2)); } Ниже будут подробно описаны отдельные поля векторной таблицы связи и приведены примеры использования информации из этой таблицы. |