Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Операционная система 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:

(-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----------------
(+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

Функция 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));
}

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

[Назад] [Содеожание] [Дальше]