(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 | неформатированная область параметров, заполняется при запуске программы из командной строки |
Для обращения к полям PSP файл sysp.h содержит следующее определение: #pragma pack(1) 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; #pragma pack()
Приведем программу, определяющую адрес первого блока MCB: /** *.Name get_fmcb * *.Title Получить адрес первого MCB * *.Descr Функция возвращает адрес первого блока MCB * *.Params MCB far *get_fmcb(CVT far *cvt) * * cvt - адрес векторной таблицы связи * *.Return Указатель на первый блок MCB **/ #include "sysp.h" MCB far *get_fmcb(CVT far *cvt) { return((MCB far *)FP_MAKE(cvt->mcb_seg,0)); }
В качестве аргумента функции get_fmcb необходимо передать указатель на векторную таблицу связи, полученный с помощью описанной ранее функции get_mcvt.
Для получения адреса следующего MCB можно использовать функцию get_nmcb: /** *.Name get_nmcb * *.Title Получить адрес следующего MCB * *.Descr Функция возвращает адрес следующего блока MCB * или 0, если это последний блок. В качестве * параметра используется указатель на предыдущий * блок MCB * *.Params MCB far *get_fmcb(MCB far *mcb) * * mcb - адрес предыдущего MCB * *.Return Указатель на следующий блок MCB или 0, если * это последний MCB **/ #include <dos.h> #include "sysp.h" MCB far *get_nmcb(MCB far *mcb) { unsigned seg, off; if(mcb->type == 'M') { seg = FP_SEG(mcb) + mcb->size + 1; off = FP_OFF(mcb); return((MCB far *) FP_MAKE(seg,off)); } else return ((MCB far *)0); }
В завершение описания блоков управления памятью приведем программу, выводящую некоторую информацию об активных MCB. Эта программа определяет адрес векторной таблицы связи, получает из этой таблицы адрес первого MCB и сканирует весь список MCB. #include <dos.h> #include <stdio.h> #include "sysp.h" void main(void); void main(void) { CVT far *cvt; MCB far *mcb; printf("\nБлоки управления памятью (MCB)" "\nCopyright (C)Frolov A., 1990\n" "\nАдрес MCB Тип Владелец Размер" "\n--------- --- -------- ------" "\n"); cvt=get_mcvt(); mcb=get_fmcb(cvt); for(;;) { if(mcb == (MCB far *)0) break; printf("%Fp %c %04X %04X\n", mcb, mcb->type, mcb->owner, mcb->size); mcb=get_nmcb(mcb); } exit(0); }