The Program Segment Prefix (PSP) is the 256 bytes DOS builds in front of every program
it runs, COM or EXE. It is not in the file. In a COM program it is the first 256 bytes of
the program’s own segment, so the program can read it at offsets 00h to
FFh, and the file’s first byte is at 100h. An
MZ program has one too, in the paragraphs just before
its load module, with DS and ES pointing at it when it starts.
The fields
| Offset | Size | Contents |
|---|---|---|
00h | 2 | INT 20h (CD 20): the exit call, where a RET with the starting stack lands |
02h | 2 | The segment of the first byte past the memory given to the program |
04h | 1 | Reserved |
05h | 5 | A far call into DOS, in the place of CP/M’s system entry; its offset word also holds the size of the program’s segment |
0Ah | 4 | The terminate address (INT 22h vector) to restore when the program ends |
0Eh | 4 | The Ctrl-Break address (INT 23h vector) to restore |
12h | 4 | The critical error address (INT 24h vector) to restore |
16h | 2 | The parent’s PSP segment, usually COMMAND.COM’s (internal) |
18h | 20 | The job file table: the program’s file handles, one byte each, FFh when unused (internal) |
2Ch | 2 | The segment of the program’s environment |
2Eh | 4 | SS:SP on entry to the last INT 21h call (internal) |
32h | 2 | The number of entries in the job file table (internal) |
34h | 4 | A far pointer to the job file table, which a program can move to have more than 20 handles (internal) |
38h | 4 | A pointer to the previous PSP, used only by SHARE from DOS 3.3 |
3Ch | 4 | Reserved |
40h | 2 | The DOS version to report to the program, from DOS 5 (SETVER changes it) |
42h | 14 | Reserved |
50h | 3 | INT 21h then RETF (CD 21 CB): a far call here does a DOS call |
53h | 2 | Reserved |
55h | 7 | Reserved; room to turn the first FCB into an extended FCB |
5Ch | 16 | The first file control block, filled from the first argument |
6Ch | 20 | The second file control block, filled from the second argument; overwritten if the first is opened |
80h | 1 | The length of the command tail |
81h | 127 | The command tail, ending with 0Dh |
The fields marked internal belong to DOS. Programs read them, but their meaning is not guaranteed between versions.
The command line
Offset 80h holds the number of characters typed after the program’s
name, and 81h on holds them, starting with the space that separated them
from the name and ending with a carriage return (0Dh) that the count leaves
out. Redirections such as > file have been taken out by the command
shell. 127 bytes is the most there is room for.
Offsets 80h to FFh are also the default disk transfer area,
the buffer that the FCB services and the find-file services (4Eh,
4Fh) write into until the program sets another with service
1Ah. A program that wants its command line must read it before it uses any
of those.
Some later shells pass longer command lines through the environment in a
CMDLINE variable; a program that finds the count non-zero and an
environment can look there first.
The file control blocks
File control blocks are CP/M’s way of naming a file, and DOS 1 used them for all file
access. DOS parses the first two arguments of the command line as file names and puts
them, unopened, in the two FCBs at 5Ch and 6Ch: a drive
number, then an eight-character name and a three-character extension, padded with
spaces. Programs from DOS 2 on use handles instead, but the parsed names are still
there, and the drive check behind AL and
AH at the start comes from them.
The environment
The word at 2Ch is the segment of a copy of the environment: a run of
NAME=value strings, each ending with a zero byte, and one more zero byte
at the end. From DOS 3, a word count of 1 and the full path of the program follow it,
which is how a program finds the file it was run from.
Finding the PSP
A COM program’s PSP is at offset 0 of its own segment, so it never needs to look for
it. An EXE program finds it in DS and ES at the start, and any program can ask for it
later with INT 21h service 51h or 62h, which return its
segment in BX.
CP/M’s page zero
The first 256 bytes follow CP/M’s layout, so that programs translated from CP/M
found things where they expected: CP/M has a jump to its warm start at
0000h where DOS has INT 20h, a jump into the system at
0005h where DOS has its far call, the default FCB at 005Ch,
and the command line and default buffer at 0080h. See
From CP/M.