(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 такую информацию, как параметры командной строки при запуске, размер доступной памяти, найти сегмент области переменных среды и т.д.
Как программе узнать адрес своего PSP? Очень просто сделать это для программ, написанных на языке ассемблера: при запуске программы этот адрес передается ей через регистры DS и ES. То есть этот адрес равен DS:0000 или ES:0000 (для COM-программ на PSP указывают также регистры CS и SS).
Для программ, составленных на языке Си, доступна глобальная переменная _psp типа unsigned. Эта переменная содержит сегментный адрес PSP.
В качестве примера приведем текст программы на языке ассемблера, которая выводит на экран передаваемые ей через PSP параметры запуска: .MODEL tiny DOSSEG .STACK 100h .DATA parm_msg DB "Укажите параметры", 13, 10, "$" .CODE .STARTUP mov cl,ds:80h ; количество символов ; в командной строке cmp cl,0 je ask_parm ; нет параметров - просим ; задать параметры mov si,81h ; со смещением 81h ; начинается область ; параметров cld get_parm: lods BYTE PTR es:[si] ; загружаем в al ; очередной ; символ строки ; параметров mov ah,2 ; выводим его на экран mov dl,al int 21h loop get_parm jmp end_progr ask_parm: mov ah, 9h mov dx, OFFSET parm_msg int 21h end_progr: .EXIT 0 END
Приведенная ниже программа, составленная на языке Си, определяет адрес своего PSP, затем показывает содержимое некоторых полей из PSP: #include <stdio.h> #include <stdlib.h> #include <dos.h> #include "sysp.h" void main(void); void main(void) { PSP far *psp_ptr; psp_ptr = FP_MAKE(_psp,0); // Конструируем указатель // на PSP printf("PSP расположено по адресу: %Fp\n" "Доступно памяти, байт: %ld\n" "PSP родительской программы: %Fp\n" "\n", psp_ptr, (long)(psp_ptr->mem_top)*16L, FP_MAKE(psp_ptr->parn_psp,0)); exit(0); }
Используя поле parn_psp, можно определить адрес PSP родительской программы, то есть программы, запустившей Вашу программу.
Немного о назначении полей term_adr, cbrk_adr, crit_err.
Поле term_adr содержит значение, полученное из таблицы векторов прерываний для вектора 22h. Это адрес программы, которая получает управление, когда текущая программа завершает свою работу. Это может быть, например, COMMAND.COM. Программа может создать свою собственную подпрограмму, которая будет получать управление при завершении работы основной программы. Она может записать свой собственный адрес в вектор 22h, затем запустить другую программу. В таком случае в запущенной программе это поле в ее PSP будет содержать адрес родительской программы. Когда основная программа завершает свою работу, DOS восстанавливает адрес программы завершения в векторе 22h из поля term_adr PSP.
Поле cbrk_adr содержит адрес программы обработки прерывания по нажатию Ctrl-Break из вектора 23h таблицы векторов прерываний. Так как программа может устанавливать свою собственную программу обработки прерывания по Ctrl-Break, DOS при завершении работы программы восстанавливает оригинальное значение из поля cbrk_adr.
Аналогично поле crit_err предназначено для восстановления содержимого вектора 24h - адреса обработчика критических ошибок.
Способы переназначения векторов будут приведены в разделе, посвященном прерываниям.
Конечно, программы, составленные на языке Си, не обязательно должны использовать PSP для доступа к параметрам командной строки и переменным среды. Для этого есть параметры функции main и набор функций типа getenv, putenv и т.п., предназначенных для работы со средой. Но ведь PSP содержит и другую информацию!