5.1.2          Префікс сегменту програми

Префікс сегменту програми (PSP) передує у пам’яті коду програми, займає 100h байт і завжди вирівнюється по границі параграфу (16 байт). При заповненні PSP програма використовує інформацію з таблиці векторів переривань та інформацію, яка повідомляється функціональному виклику ЕХЕС. Формат PSP наведений в Табл. 11. Сегментна частина адреси початку в PSP (пізніше для зменшення називатимемо її сегментом PSP) – це унікальна програма-ідентифікатор. По аналогії з ОС UNIX його часто називають ідентифікатором програми, чи РІD (Program IDentifier).

Табл. 11. Формат префікса сегмента програми

Зсув від початку PSP

Використання

00Н

Код для завершення програми

02Н

Сегмент верхнього границі блока пам’яті, який зайнятий програмою зарезервовано (дорівнює 0000)

04Н

Зарезервовано

05Н

Машинний код far-виклику DOS-диспетчера

0АН

Адреси обробнику завершення (ІР, CS)

0ЕН

Адреси обробнику CTRL-BREAK (IP, CS)

12Н

Адреси обробнику критичних помилок функції MS-DOS (IP, CS)

16Н

Сегмент PSP програми-батька (PID батька)

18Н

Таблиця відкриття файлів програми

2СН

Сегмент середовища програми

2ЕН

Адреси стеку при виклику функції MS-DOS (SP,SS)

32Н

Розмири таблиці відкритих файлів програми

34Н

Адреси (seg, ofs) таблиці відкритих файлів програми

38Н

Зарезервовано

5СН

Невідкритий блок Керування файлом (FCB) номер 1

6СН

Невідкритий блок Керування файлом (FCB) номер 2

80Н

Область переносу диска (DTA) по замовченні, або “хвостовик” командної рядка

Далі дається описання деяких з полів PSP.

5.1.2.1      Код для завершення програми – PID:0000h (2 байта)

Звичайне завершення програми в MS-DOS є виконання переривання 20h. Тому, два перших байти PSP рівне CDh 20h, утворює машинний код інструкції INT 20h. Взагалі, тут може розміщуватися і інший машинний код, наприклад інструкції INT27h для резидентного завершення СОМ-файлів, “короткий” безумовний перехід (JMP SHORT) та інше.

5.1.2.2      Сегмент верхньої границі блоку пам’яті – PID:0002h (2 байта)

При завантаженні програми на виконання MS-DOS продивляється низку МСВ-блоків пам’яті. Знайшовши перший же вільний блок, розмір котрого не менший ніж розмір програми, MS-DOS в цілому виділяє його програмі. Якщо пам’ять не фрагментовано, PID:0002h зберігає сегмент верхньої пам’яті комп’ютера.

5.1.2.3      Адреси обробника завершення – PID:000Аh (4 байта)

По цьому адресу MS-DOS передає керування при завершенні програми. Дана адреси копіюється з таблиці векторів переривання (переривання 22h) в момент побудови PSP. Вектор переривання 22h вказує на системний обробник завершення програм .Не слід переривання 22h викликати безпосередньо це робить функціональний виклик ЕХЕС.

5.1.2.4      Адреси обробника Ctrl-Break – PID:000Eh (4 байта)

В цьому полі MS-DOS запам’ятовується вектор переривання 23h, а після завершення програми заново переписує його в ТВП, відновлює реакцію на Ctrl-Break. Вектор переривання 23h вказує на обробник натиснення комбінації клавіш Ctrl-Break (Ctrl-С). Стандартний обробник переривання 23h входить в резидентну частину COMMAND.COM. Він викликається функціями MS-DOS, якщо вони знаходять під час свого виконання, що прапор натиснення Ctrl-Break встановлено. Перевірка прапору виконується більшістю функцій, пов’язаних зі стандартним введенням, виведенням, друком, асинхронним зв’язком. Число функції збільшується, якщо внутрішня змінна MS-DOS встановлена в стан ON командою BREAK (BREAK ON).

5.1.2.5      Адреси обробника критичних помилок – PID:0012h (4 байта)

В цьому полі MS-DOS запам’ятовує вектор переривання 24h, а після завершення програми заново переписує його в ТВП, відновлюючи реакцію на критичні помилки. Вектор переривання 24h вказує на обробника системних помилок, що з’являються при виконанні функцій MS-DOS. Стандартний обробник переривання 24h входить у резидентну частину COMMAND.COM. Встановивши помилку при виконанні своєї функції, MS-DOS виконує програмне переривання 24h. Стек при виклику переривання знаходиться у відомому стані та дозволяє визначити адресу повернення в прикладну програму. Стандартний обробник, наприклад, вказує користувачу на помилки читання з диску та очікування відповіді користувача (Abort, Retry, Ignore чи Fail). Обробник переривання 24h вказує в MS-DOS про зроблений вибір значенням в регістрі AL:

         якщо вибір – “Ignore” (ігнорувати), то AL=0 (не рекомендується використовувати; MS-DOS буде продовжувати, якщо це фізично можливо, виконання функції);

         якщо вибір – “Retry” (спробувати ще раз), то AL=1 (знову викликається функція MS-DOS при виконанні якої була зафіксована помилка);

         якщо вибір – “Abort” (аварійне завершення поточної програми), то AL=2 (MS-DOS негайно викликає обробник завершення, тобто програму, на яку вказує вектор переривання 22h);

         якщо вибір – “Fail” (завершити функцію з видачею коду помилки), то AL=3 (керування повертається в MS-DOS, звідки відразу ж передається у прикладну програму з індикатором помилки (звичайно це встановлений в 1 прапор переносу CF)).

Відмітимо, що MS-DOS відтворює значення векторів 22h, 23h, 24h при кожному завершенні програми, використовуючи значення, що зберігаються у PSP. Змінивши вектори у PSP, програма може примусити нащадків наслідувати не системні, а свої обробники переривань 22-24h.

5.1.2.6      Сегмент PSP програми-батька – PID:0016h (2 байта)

Має сегмент адреси PSP програми-батька (PID батька). Для багатьох програм батьківською програмою є COMMAND.COM. У нього немає батька, і тому це поле у PSP COMMAND.COM має сегментну адресу свого PSP, тобто вказує на себе. Переглядаючи PSP всіх програми у пам’яті, починаючи з PSP COMMAND.COM., можливо встановити “історію” завантаження програм з моменту завантаження MS-DOS.

5.1.2.7      Сегмент середовища програми – PID:002Сh (2 байта)

Представляє собою сегмент адреси блока пам’яті, що зберігає рядки середовища програми. Програма при завантаженні на виконання займає два блоки пам’яті: блок, в якому розташоване середовище, та блок, що містить код, дані та стек програми. Середовище – це послідовність текстових рядків (загальним об’ємом менше 32 Кбайт), які мають вигляд:

NAME = параметр

Кожен рядок середовища закінчується нульовим байтом (так званий ASCIIZ-рядок), та весь набір рядків завершується ще одним нульовим байтом. Після цього розташовується набір аргументів, включаючи рахівник символів (2 байта) та текстовий рядок повної специфікації (накопичувач, шлях, ім’я файлу, розширення) завантаженої на виконання програми.

Середовище нащадка часто унаслідується від батька, тобто є повною копією середовища батька. Якщо батьківською програмою виступає COMMAND.COM, вона, як мінімум, має рядок:

COMSPEС = рядок

де параметр “рядок” вказує маршрут для визначення COMMAND.COM на диску. В середовищі також будуть розміщуватись й інші рядки, встановлені завдяки командам MS-DOS: PATH, PROMPT і SET. Всі зміни в середовищі, зроблені нащадком, змінюють будову блоку середовища нащадка і не викликає зміни в блоці середовища батька.

5.1.2.8      Адреси стеку при виклику функцій MS-DOS – PID:002Еh (2 байти)

Починаючи свою роботу, функції MS-DOS переключають стек. Значення SP та SS на момент виклику функції зберігаються у PSP, а при виході з MS-DOS повертаються в попередній стан.

5.1.2.9      Невідкритий (FCB) номер 1 – PID:005Еh (16 байта)

Якщо в командному рядку при завантаженні програми є параметри, перше слово “розбивається” MS-DOS як ім’я файлу і для нього будується “рудиментарний” блок Керування файлом (FCB).

5.1.2.10  Невідкритий (FCB) номер 2 – PID:006Еh (16 байта)

Теж саме, але поясненню підлягає друге слово командного рядка. Блоки керування файлами використовуються програмами, розрахованими на роботу під керуванням MS-DOS версії 1.0.

5.1.2.11  Дані – PID:0080h (128 байта)

Якщо програма використовує “рудиментарні” FCB-функції для доступу до файлів, це поле працює дисковим буфером. Воно використовується також функціями MS-DOS, які виконують пошук у директоріях (бібліотечні аналоги: findfirst() та findnext()). У всіх інших випадках область використовується для прийому “хвостовика” командного рядка. У цьому випадку вона має формат:

PID:(PSP+80h) довжина “хвостовика”;

PID:81h-PID:100h символи “хвостовика”, які завершується символом CR.

Формування “хвостовика” виконує батьківська програма. Якщо батьківською програмою є COMMAND.COM, “хвостовик” має всі символи, введені після імені файлу. Лишні пробіли між словами знищуються. Якщо в командному рядку зустрічаються символи переадресації стандартного введення-виведення “<”,”>”,”|”, то ні вони, ні пов’язані з ними імена файлів не будуть включатися до “хвостовика”. Наприклад, якщо з командного рядка запускалась деяка програма CMDLINE п’ятьма різними способами:

A: > CMDLINE This is a test
A: > CMDLINE This >is a test
A: > CMDLINE This \is\a\test
A: > CMDLINE This is < a test
A: > CMDLINE This | is a test

то результати були б такі: в першому випадку зі зміщенням 81h PSP був би записаний рядок This is a test\xd. У другому випадку COMMAND.COM відкрив би файл з ім’ям IS, куди помістив би весь вивід на stdout з програми CMDLINE, і в PSP зі зміщенням 81h був би записана рядок This a test\xd, а в третьому випадку – This /is/a/test. Введення четвертого рядка не викличе ніяких дії, так як файл, на який повинен бути переадресований stdin, відсутній. Тому COMMAND.COM не буде запускати на виконання програму CMDLINE. Введення п’ятого рядка викличе повідомлення про помилку, так як вивід CMDLINE (якщо він є), “конвеєризується” (переадресується) недійсній програмі IS.

У кожній програмі є свій PSP. Але MS-DOS знає тільки один PSP – який знаходиться перед програмою, запущеною останньою. Сегмент цього PSP називається ідентифікатором, чи PID (Program Identifier) активної програми. Він зберігається у внутрішній змінній MS-DOS і відновляється при кожному виконанні функції EXEC. Іншими словами, в кожний момент часу MS-DOS знає тільки про активну програму та її PSP. Це породжує ряд складних проблем, найбільше при розробці резидентних програм.