Jan 042018
Chris Dunford's memory mapper version 2.10. Displays a map of TSRs, device drivers, files, buffers, FCBs, etc. Also displays programs that may be running in high memory.
File PMAP210.ZIP from The Programmer’s Corner in
Category System Diagnostics
Chris Dunford’s memory mapper version 2.10. Displays a map of TSRs, device drivers, files, buffers, FCBs, etc. Also displays programs that may be running in high memory.
File Name File Size Zip Size Zip Type
PMAP.DOC 48691 14343 deflated
PMAP.EXE 27621 16034 deflated

Download File PMAP210.ZIP Here

Contents of the PMAP.DOC file

PMAP 2.10

PMAP (Program MAP) displays how your PC's memory is being used.
It lists all active programs (including resident programs such
as Sidekick and PCED), displays free memory areas and their
locations, identifies device drivers, summarizes expanded (EMS)
and extended (XMS) memory use, and details certain DOS data

Version 2.10 adds support for XMS (extended memory) and the HMA
(high memory area). We have found that the old switch syntax
was becoming unworkable (PMAP was designed in the good old days
when memory was memory), so we decided to bite the bullet and
change the way some of the options work. Some switches have
been renamed to conform with current terminology (/X was for
expanded memory, is now for XMS memory) and some usage has been
changed. For example, /S used to mean "display ONLY standard
memory"; no, it means "display standard memory in addition to
anything else that's selected." We apologize to anyone who has
to change batch files, etc., but we felt that the changes were

| identifies information about new features for PMAP 2.0.

Syntax summary
The command line syntax of PMAP is:

pmap [program-list] [/options]

The default behavior, if no arguments are supplied, is:

PMAP /e /s /x (or, yes, PMAP /sex)

The program-list, if present, restricts the display of resident
programs to those listed; the list may include wildcards (*).
The program list affects the standard memory display only. See
"Standard memory display", below.

| The option switches are:
| Select primary displays(s):
| /e display expanded (EMS) memory summary
| /k display data area of DOS kernel (DOS 3.0 or later)
| /r display raw list of memory blocks
| /s display standard DOS memory
| /v display device driver information
| /x display extended (XMS) memory summary
| Additional options for /s display (these all imply /s):
| /d display detail list of allocation by programs
| /f display names of open files (DOS 3.0 or later)
| /n display programs' environments
| Othe options:
| /q quick display
| ? display syntax summary

Multiple switches may be specified together or separately. All
of these are valid and equivalent:

pmap /f /d
pmap /fd
pmap /f/d

If you wish to set "permanent" options, i.e., options that will
be in effect for every PMAP run, set an environment variable
called PMAP to contain the desired option switches. For
example, if you usually want to list only standard memory, with
file handles, set PMAP as follows:

SET PMAP=/s /f

To override options set in the PMAP variable, you can follow
any switch with an asterisk. For example, if you have the PMAP
variable set as above but do NOT want to see the file handles
for one run, use:

pmap /f*

| Selecting the primary display(s)
| --------------------------------
| PMAP provides six primary displays:
| - standard (conventional) DOS memory (/s option)
| - expanded (EMS) memory (/e)
| - extended (XMS) memory (/x)
| - the system kernel (/k)
| - device drivers (/v)
| - raw statndard memory blocks (/r)
| By default, PMAP displays the first three; as mentioned above,
| you can change the default with the PMAP environment variable.
| The first occurrence of any of the above options, either on the
| command line or in the PMAP variable, turns off all of the
| others. Thus, if you type
| pmap /sk
| You will see only the standard memory and kernel displays--the
| EMS and XMS displays are turned off. Similarly, if you use
| you will, by default, see only the expanded (EMS) memory
| display.
| Primary options set on the command line turn off any primary
| options set in the PMAP variable:
| ...
| pmap /x
| In the example, only extended memory is displayed.
| Note that the /d, /f, and /n options all imply /s, since they
| affect only the standard memory display. Thus,
| pmap /d
| is equivalent to
| pmap /sd
| and will display only standard memory (including the details
| requested by /d).

Standard memory display
The display of standard (conventional) DOS memory looks similar
to this:

Addr Program Parent Parameters Han Blks Size Vectors
---- ------- -------- --------------- --- ---- ------- -------
147D command command main 0 2 3888 2E
157B nmi command /i/q 0 2 1856 02
15F2 cache-em command 500 0 2 13168 13 19
193E dbase command /C d:command 16 2 238384 30
Other allocated blocks 4 81296
Total conventional free memory 4 451696
Largest conventional free block 371168
Next program will load at 5579

Each program that is currently in memory is displayed. Fields
are as follows:

Addr The memory segment at which the program is
loaded, in hexadecimal. If an asterisk (*)
follows the address, the program is loaded
into a disconnected high memory chain (see

Program The name of the program, if available. "n/a"
indicates that the name is not available. The
program name is never available under DOS 2.x.

Parent The name of the program's "parent". In most
cases, this will be "command", because most
programs are run by COMMAND.COM (i.e., from
the DOS prompt). See below.

Parameters The command line parameters that were specified
when the program was run. Some programs re-use
the area where the parameters are stored, in
which case a "??" will be displayed. An
ellipsis ("...") at the end indicates that there
were more parameters than could fit here.

Han The number of open handles (or files) associated
with the owner. See below.

Blocks The number of memory blocks that are owned by
the program.

Size The total size of all blocks owned by the

Vectors A list of 80x8x interrupt vectors that appear to
have been "intercepted" by the program.

In the example, the program NMI is loaded at memory segment
157BH and was run directly from the DOS prompt or from a batch
file. The original parameters were "/i/q". DOS has allocated
two blocks of memory for the program, and they total 1856 bytes
in size. Vector 2 (nonmaskable interrupt) has been
"intercepted" by NMI.

"Other allocated blocks" refer to blocks of memory that are not
free but also are not owned by any executable program that PMAP
can identify. They may be owned by device drivers or by DOS
itself; or they may in fact be owned by executable programs but
not indicated as such. PMAP may be able to make an educated
guess as to the true owner; if so, the probable name of the
program will be indicated in parentheses when you use the /D
option switch (see below).

At the end of the list, PMAP indicates the number of blocks of
free memory, the total size of all free blocks, the largest
single free block, and the segment address at which the next
program will probably load.

You can restrict the display to certain programs by naming them
on the command line. For example, the command

pmap sdump ced

would display information for the SDUMP and CED programs, and no

You can use a single wildcard '*' at the end of any named
program in the list. For example,

pmap sd* c*

would display information for all programs beginning with
"sd" or "c".

NOTE: "below" the first program loaded in memory (usually
COMMAND.COM), there is a block of memory allocated by DOS for
device drivers, etc. PMAP does not show this block in the
main display; its size is indicated under "Other allocated
blocks" area if you request a detailed listing (/D), and further
detail is available with the /K switch (see below).

Detail display (/D)
When you run PMAP with the /D (Detail) option, you'll see the
same display, except that PMAP will show a detailed list of
memory blocks allocated for each program. For example:

Addr Program Parent Parameters Han Blks Size Vectors
---- ------- -------- ------------- --- ---- ------- -------
1666 kbfix2 command /KT1 /D0... 0 2 2560 08 09 16
1661 Environment 64
1666 Program 2496

KBFIX2 has two memory blocks allocated to it; PMAP shows the
size of each block and its address, and makes an educated guess
as to what the block is used for.

You may include a list of specific programs to be displayed:

pmap sdump ced /d

PMAP also displays a detail list of all free blocks of memory
and of "other allocated blocks".

Environment display
If you add a /N switch, PMAP will display the contents of each
program's environment (if there is one). For example, the

pmap rxrun /n

might display something like this:

Addr Program Parent Parameters Han Blks Size Vectors
---- ------- -------- ------------- --- ---- ------- -------
B6D4 rxrun command 0 2 1536
Environment [B7E3]

The [B7E3] represents the segment address at which the
environment is located.

The [name] field appears only under DOS 3.0 and later; it shows
the contents of the area of the environment where the full path
and name of the program are stored. In some cases (especially
in the case of COMMAND.COM), garbage may in fact be stored in
this area. If PMAP think that the field is invalid, it will
report "[name field invalid]"; however, PMAP may display invalid
data if the contents of the field look like displayable characters.

Open files display (/F)
If the HAN field in the standard display is non-zero, the named
program currently has files that are open. You can display the
names of these files by adding the /F option. For example:

Addr Program Parent Parameters Han Blks Size Vectors
---- ------- -------- ------------- --- ---- ------- -------
12CD command command /f 1 2 4176 22 23 24 2E
Open files: D:FOPT.TXT

This feature is available only under DOS 3.0 and later and is
mutually exclusive with the /Q (Quick) switch.

Quick display (/Q)
Some of what PMAP does can be somewhat time consuming on slower
computer systems, and one task may fail under some versions of
DOS. If you would like PMAP to run slightly faster (about 1/2
second on a 4.77Mhz machine if you have EMS) or if PMAP fails
with an error message similar to:

pmap: error tracing buffer chain

then use the /Q (Quick) option switch. With /Q set, PMAP will

1. Search for a disconnected high memory chain, or
2. Look for buffers, files, stacks, etc.

The /K and /F options cannot be used with /Q. Also note that /Q
will have little effect on PMAP's speed unless you have expanded
memory (EMS), and that /Q is automatically set for DOS versions
prior to 3.0.

Remember, if you always want to use the /Q switch, you can


in your environment.

Kernel display (/K)
Below the first program loaded into memory (usually COMMAND.COM)
there is an area of memory used by DOS for storage of code and
data. This area is broken into three major sections:

1. IBMBIO's code and data. This is always located at memory
segment 0070h and contains the basic code and data for
system input/output services. The default device drivers
(for the printer, screen, and keyboard, etc.) are also
located here.

2. IBMDOS's basic code and data. This is located in memory
immediately following IBMBIO's area and contains the "guts"
of DOS. This area usually includes space for five FILES
and one BUFFER. (Under DOS 5.0 with DOS=HIGH, part of this
area is moved to the HMA.)

3. A supplementary DOS data area. This area may include:
- your FCBs; the size is affected by the FCBS option
in your CONFIG.SYS.
- any FILES beyond the initial number (usually 5) that
are stored in the IBMDOS area. This size of this area
is determined by the FILES option in CONFIG.SYS.
- any BUFFERS beyond the initial number (usually 1) that
are stored in the IBMDOS area. The size of this area
is determined by the BUFFERS option in CONFIG.SYS.
- your logical drive table. There is one entry in this
table for each drive up to LASTDRIVE.
- your DOS STACKS, if any (DOS 3.1 or later only). The
size of this area is determined by the STACKS option
- any externally loaded device drivers such as ANSI.SYS.

To display a detailed map of the complete DOS memory area (all
three of the above), use the /K option. The display might look
something like this:

MCB Addr End Size Contents
---- ---- ---- ----- --------
-- 0070 0279 8352 IBMBIO [includes 13 device drivers]
-- 027A 09C7 29920 IBMDOS [includes 5 files, 1 buffer]
09C8 09C9 1282 35760 DOS data/drivers

DOS data/drivers area detail:
09C9 0E9B 19760 8 device drivers (PMAP /V for detail)
0E9C 0F10 1872 35 files
0F11 0F1E 224 4 FCBs
0F1F 1191 10032 19 buffers
1192 11B5 576 7 logical drives
11B6 1282 3280 9 stacks (128 bytes each)

The first section shows the locations and sizes of the three
major areas used by DOS. In this case, for example, area 2 (the
basic IBMDOS code/data area) begins at memory segment 027Ah and
is 29,920 bytes in size. It includes five files and one buffer.

The MCB field, which only appears for area 3, shows the address
of the memory control block for the area. This is part of DOS's
memory management scheme and is decribed in greater detail later
in this manual. Areas 1 and 2 are not part of DOS's official
memory chain, so they have no MCBs.

The second section breaks down the contents of area 3 in greater
detail. In the example system, eight device drivers are
loaded and the system is configured as follows:


The display shows the exact location and size of each of these
items. For example, the extra 19 buffers (there's one in area
2, leaving 19 of the 20 for area 3) are located at memory
segment 0F1Fh and extend through the end of memory segment
1191h, a total of 10,032 bytes.

If you use an extender program such as QEMM's FILES.COM to
increase the number of FILES after bootup, storage for the extra
files will be located elsewhere in the memory chain--not in
any of the DOS data areas described. PMAP will display such
areas in a separate section if there are any. For example, if
we ran:


to increase the maximum number of files from 40 to 42, the
display might appear as follows:

Additional memory block(s) used for DOS data:
MCB Addr End Size Contents
---- ---- ---- ----- --------
1897 1898 18C8 784
>> 18C1 18C7 112 2 files

This shows that the 944-byte block from 1403h to 143Dh (with MCB
at 1402h) is used for supplementary DOS data. Within this
944-byte allocation, the 272 bytes from memory segments 142Ch
through 143Ch contain the actual storage for information about
the five files.

Note also that, if there are additional blocks such as these,
they are identified in the standard program display if you use
the /D (detail) option. The above might look something like
this in the detail display:

Addr Program Parent Parameters Han Blks Size Vectors
---- ------- -------- ------------- --- ---- ------- -------
1898 n/a command +2 0 1 784
1898 2 files 784

The /K option is available only under DOS 3.0 and later.

Raw display (/R)
When you run PMAP with the /R (Raw) parameter, you'll see a
display like this:

T MCB Addr Owner Para Bytes
- ---- ---- ----- ---- --------
M 0974 0975 0008 0AFA 44960
M 146F 1470 1470 00C3 3120
M 1533 1534 1470 0020 512 GLVMGR
[more of the same]
M 1DF3 1DF4 1DF4 0706 28768
M 24FA 24FB 2500 0004 64 [pmap]
M 24FF 2500 2500 1376 79712 [pmap]
Z 3876 3877 0000 6789 424080

This is an uninterpreted list of all blocks of memory allocated
by DOS (see below). The fields are as follows:

Type The block type. There are only two block types,
type M and type Z. The last block in the
chain is type Z, and all others are type M.

MCB The segment address of the Memory Control Block
(sometimes known as an arena header).

Addr The segment address of the memory block itself.
This is always equal to the MCB address plus

Owner The segment address of the program that "owns"
the block of memory. If this is 0000, the block
is unallocated or "free".

Para The size of the block, in paragraphs (16 bytes).

Bytes The size of the block, in bytes.

All numbers are hexadecimal except "bytes", which is decimal.

The [pmap] suffix after an allocated block indicates that the
block is being used by PMAP. When PMAP terminates, this block
will be free (unallocated). The standard (non-raw) PMAP display
understands this, and displays the map as if PMAP weren't there.

Following some lines on the display you may see a one- to
eight-character string:

T MCB Addr Owner Para Bytes
- ---- ---- ----- ---- --------
M 1533 1534 1470 0020 512 GLVMGR

Under DOS 4.0 and later, a program name may appear in the last
eight bytes of a memory control block (which is what the raw
display is showing). Under DOS versions prior to 4.0, DOS does
not place the program name in this location, but some other
programs (such as 386MAX and QEMM) may do so. If PMAP thinks
that the contents of the last eight bytes of the MCB look like a
readable string, it will display the string. This may provide
some information about the owner of the block. In some cases,
the information in this area may be garbage that happens to
consist of all ASCII characters--and these will be displayed.
You should be able to tell at a glance which strings are
meaningful and which are not.

If PMAP is able to identify a disconnected high memory chain, it
will display the line:

Disconnected high memory chain:

between the regular low-RAM DOS memory chain and the "hidden"
high memory chain.

If the /R switch is included, all other command line parameters
are ignored.

Expanded memory display (/E)
If expanded (LIM or EEMS) memory is present and you have not
specified /E*, PMAP displays EMS allocation as follows:

Expanded memory summary:

Block Size Name
----- ------- ----
0 589824 SYSTEM
1 425984
2 16384 CDIR
3 65536 HINDSITE
Free 327680
Total 2097152
Page frame segment: CC00h

The NAME field will be present only if your expanded memory
manager supports the LIM 4.0 specification, and then only for
programs that have defined their names to the system.

EMS memory uses a "page frame" that maps a 64K block (actually,
four 16K "pages") of EMS memory into standard 80x8x memory.
The segment to which this memory is mapped is also displayed.

| Extended memory display (/X)
| ----------------------------
| If extended memory (XM) is present and you have not specified
| the /X* option, PMAP displays XM information as follows:
| Extended memory summary:
| INT 15 ext mem available 0
| XMS version 3.00 (vendor 5.12)
| HMA enabled, in use
| Free XMS 458752
| Largest free block 458752
| XMS handles in use:
| Handle Size Address LkCt
| 1 32768 00110000 1
| 2 277504 00118000 --
| "INT 15 ext mem" refers to AT-style extended memory that is not
| managed by an XMS driver. This type of memory is used primarily
| by older devices such as VDISK.
| The remaining information is shown only if an XMS (eXtended
| Memory Specification) driver is present in the system. XMS
| drivers manage extended memory by allocating and providing
| access to blocks of XM as requested by system and application
| programs. Among such drivers are DOS's HIMEM.SYS, Qualitas's
| 386MAX, and Quarterdeck's QEMM.
| "XMS version" is the version number of XM Specification that is
| supported by your XMS driver. Following this is the vendor's
| internal version number for the driver software.
| "HMA" refers to the High Memory Area, a block of memory
| approximately 64K in size at the very top of your CPU's real
| mode address space. The HMA is special because it includes the
| only addresses above 1MB that can be accessed by the CPU in real
| mode (which is the mode DOS normally uses). Current XMS
| managers allocate this space to one, and only one, program at a
| time. HMA is the are of memory that is used by DOS 5.0 when
| DOS=HIGH is specified (thus moving most of DOS out of the lower
| 640K). PMAP's report shows whether or not the HMA is enabled
| and, if so, whether or not it is in use.
| "Free XMS" shows the total amount of XMS-managed extended memory
| that is current available for allocation, in bytes. "Largest
| free block" shows the size of the largest single free block of
| XMS-managed memory.
| If any XMS-managed memory is currently allocated, the "XMS
| handles in use" section displays additional information. For
| each active XMS "handle" (each block of extended memory
| allocated by the XMS manager is assigned a handle), PMAP
| displays the handle number, the size of the block in bytes, and
| the 32-bit linear address of the block (in hex). If the block
| is currently "locked" (guaranteed not to move), PMAP displays
| its non-zero "lock count", which is the number of times it must
| be unlocked before it is once again movable. Most blocks should
| be unlocked most of the time.

Device driver display (/V)
If you execute PMAP with the /V switch, it will display a table
of information about your installed device drivers. No other
data (i.e., no memory maps) are displayed when /V is selected.

The first five columns of the table contain the following

Name If the device is a character device, the device
name. If it is a block device (like a disk),
this will be "Blk (n)", where n is the number
of units handled by this device.

Address The address where the device driver begins in
memory, in standard hex segment:offset form.

Size The approximate size (in bytes, displayed in
decimal) of the device driver. See below.

Strt The entry point of the driver's strategy
routine. This is the hex offset within the
device driver's segment (shown under ADDRESS).

Intr The entry point of the driver's interrupt
routine. This is the hex offset within the
device driver's segment (shown under ADDRESS).

The remaining columns are bit fields with the driver's attribute
record. In each case, an asterisk indicates that the bit is
set (1), and a space indicates that it is reset (0).

CHR * = this is a character device
= this is a block device.

IOC * = device supports IOCTL calls

IBM for block devices:
* = non-IBM format
for character devices:
* = supports output-until-busy

RMV * = supports removable media

LOG * = supports Get/Set Logical Device

CLK * = this is the clock device

NUL * = this is the NUL device

SOT * = this is this standard output device

SIN for block devices:
* = supports generic IOCTL
for character devices
* = this is the standard input device

Note that implies the opposite of <*>; for example, an
asterisk in IOC indicates that the device supports IOCTL calls,
while a space there indicates that IOCTL is not supported.

Also note that DOS does not provide any documented way for
programs to find the chain of device drivers. If PMAP is unable
to find the chain, it will tell you so.

Device driver size; order of list
PMAP cannot reliably determine the size of the default devices
(CON, PRN, AUX, COM1, etc.) that are loaded automatically by DOS
(they share code and data). These will all show an address
beginning with "0070", and their sizes will not be displayed.
However, if you load a replacement for one of these devices (for
example, ANSI.SYS loads a replacement for CON), PMAP will
generally be able to determine and display its size.

The devices are shown in the order in which DOS searches for
them. If there are two or more devices with the same name, the
one that DOS will use is the first one listed. For example, you
will have two or more CON devices if you use ANSI.SYS; the
ANSI.SYS CON will be listed before the default CON. DOS will
use the first one listed (ANSI.SYS).

Disconnected high memory chains
DOS manages memory by using a "chain" of allocated memory blocks
as described below. This chain normally ends at the 640K mark
(segment A000), as memory addresses above this address are
reserved for use by video adapters (some programs such as
EEMRAM, QEMM, and 386MAX may extend the chain to B000 or B800).
By following the links in this chain, PMAP is able to map your
DOS memory and determine what programs own what areas of memory.

However, Quarterdeck's QEMM and Qualitas' 386MAX may create an
additional chain of allocated memory blocks in "high RAM" above
the video adapter memory area. Using a "high load" feature,
these programs can load your resident utilities and device
drivers into the high RAM chain, thus increasing the memory
available to DOS in low RAM.

The high RAM chain is not connected to DOS's standard low RAM
chain (unless you use 386MAX's OPENHIGH option), and versions of
PMAP prior to 2.0 would not find it; therefore programs loaded
into high RAM were not displayed.

Beginning with version 2.0, however, PMAP attempts to locate
these "high memory chains" and identify the programs loaded
there. If PMAP succeeds in finding the chain and there are
programs loaded in it, such programs will be marked with an
asterisk (*) in the program display. In raw block display mode
(/R), the two chains (low and high) are shown separately.

NOTE: PMAP has no internal knowledge of QEMM, 386MAX, or
similar programs; the presence of high memory chains is
determined empirically. The possibility exists that PMAP may
occasionally report an artifact chain: something that looks to
PMAP like a high memory chain but really isn't. You should be
able to tell by looking at the displays (especially the /R raw
display) if such a chain has been found.

Interrupt vectors
Many times interrupts are "intercepted" by more than one
resident program. PMAP will only show a vector attached to the
LAST program that intercepted it. For example, in the sample
display shown for the /D (Detail option), KBFIX2 shows that it
has intercepted vectors 8, 9, and 16. However, RXINTMGR and
SDUMP could also have intercepted any or all of these three
vectors, and PMAP would not know about that.

PMAP assumes that any vector that points into memory owned by a
program has been intercepted by that program. That is not
always true, so you may occasionally see spurious vectors
attached to a program.

More about parents
Every program has a "parent"; if program B was executed by
program A, then A is B's parent. In most cases, the parent will
be COMMAND.COM, because most PC programs are executed by

However, any program can execute any other program (assuming
that there is sufficient memory, etc.). This is how "shells"
work. For example, current versions of WordPerfect and many
other programs allow you to "exit to DOS"; what they usually do
is execute COMMAND.COM, which then displays a DOS prompt and
allows you to enter any commands that you wish. If you run
PMAP, you will see two copies of COMMAND.COM in memory.

However, you may notice that the second copy of COMMAND.COM
shows COMMAND.COM as its parent. Logically, you would expect
the parent to be (in this case) WordPerfect. Unfortunately,
some versions of COMMAND.COM (the one that comes with DOS 3.2,
for example) fool around with the area of memory that PMAP uses
to find the parent's address; rather than having the parent's
address, COMMAND.COM puts its own address there. In effect,
COMMAND.COM is always its own parent.

In general, programs that allow you to execute other programs
can use one of two methods: they can execute the other programs
directly, or they can execute COMMAND.COM and ask it to run the
requested program. If the former case, PMAP will show the true
parent; if the latter, PMAP may show COMMAND.COM as the parent,
and COMMAND.COM will be its own parent.

Here is part of a PMAP display that shows a direct-execution
under DOS 3.2:

Addr Program Parent Han Blks Size Vectors
---- ------- -------- --- ---- ------- -------
3222 xced command 0 2 26016
387E qe xced 0 3 97232
503E command command 0 3 3488 22 23 24

The XCED program was run by COMMAND.COM (from the DOS prompt).
It then ran the program QE directly, i.e., without reloading
COMMAND.COM; QE's parent is correctly shown as XCED. Finally,
a "shell" exit was taken from QE, which did reload COMMAND.COM;
notice that COMMAND shows as its own parent. The second
COMMAND.COM's real parent is QE, but this is not shown

File handles
The "Han" field of the standard memory display shows the number
of file handles that are associated with each program. For the
most part, this field will be zero. Some open handles may show
for programs that are active (for example, the active program
named "dbase" in the first example has 16 open files).

Use the /F option to see the names of the open files.

You may see some resident programs that show one or more open
handles. This usually occurs when you redirect the program's
start-up logo to NUL, and the program fails to close its
standard files before exiting back to DOS (this really shouldn't
be necessary, but it is). These open handles may reduce the
number of files your application programs can have
simultaneously open. We prefer not to redirect programs' logos
to NUL. We save file handles; we get to see the names of the
nice people who wrote our software, and their copyrights; and we
don't lose the error messages that explain why the program isn't
doing what we thought it should. Sounds like a bargain.

Multi-tasking/task-switching programs
... play havoc with the memory allocation chain. PMAP may
not yield very much useful information under such programs.

DOS's memory allocation chain
This information is almost totally undocumented by Microsoft, so
take it for what's it's worth. It's provided for informational
purposes only, and could vary from DOS version to DOS version.
However, the basic structure of the memory allocation scheme has
remained unchanged from DOS 2.0 through the version that is
current as of this date (5.0). Only the program name field has
changed--it was added with version 4.0.

DOS (version 2.0 or later) manages memory as a chain of "blocks"
or "arenas". Each block begins on a paragraph boundary, can be
(in theory) almost a megabyte in size, and is preceded
immediately by a 16-byte Memory Control Block (MCB), sometimes
known as an "arena header". The lowest (the 80x8x interrupt
vectors, BIOS and DOS data areas, DOS itself, device drivers,
etc.) and highest (video buffers, ROM modules) portions of
memory are not mapped, but the rest of memory is. Thus, memory
can be pictured like this:

paragraph contents
0000 low memory (unmapped)
first MCB (16 bytes)
first memory block
next MCB
next memory block
last MCB
last memory allocation block
nnnn end of DOS memory (640K, for example)

The address of the first MCB will vary, depending on your
version of DOS and the number and size of device drivers,
buffers, stacks, etc., that you loaded via CONFIG.SYS. In all
current versions of DOS (verified through 5.00), the segment
address of the first MCB can be obtained via DOS function 52H.
On return from this function, the address of the first MCB is
located at ES:[BX-2]. Here is sample code that returns the
address of the first MCB in AX:

mov ah,52H
int 21H
mov ax,es:[bx-2]

The MCB itself is a 16-byte region of memory that with fields as

Offset Size Contents
------ ---- --------
0 Byte 'M': this is not the last MCB
'Z': this is the last MCB
anything else: memory control blocks
destroyed. DOS will politely crash.

1 Word The segment address of the program that owns
this block of memory (the program's PSP).

3 Word The size of the block, in paragraphs

5-7 Reserved

8-15 n/a 8-char (blank-filled) name of owner program
(DOS 4.0+ only)

This structure provides all of the information needed to step
through the memory allocation chain. A basic algorithm is as

Set MCB = segment of first MCB (as described above)
Do Until byte (MCB:0) = 'Z'
If byte (MCB:0) isn't 'M' or 'Z',
Then there's a big problem (the system is about
to crash with a "memory allocation error")
Block_owner = word (MCB:1)
Block_size = word (MCB:3)
MCB = MCB + block_size + 1

EMS and XMS memory is not mapped by DOS.

For more complete detail about DOS's memory allocation, see
"Managing Memory" by William J. Redmond in PC Tech Journal,
August, 1984 (Vol. 2, No. 2).

Version 2.10 (7/3/91)
- Adds support for XMS drivers.
- Reworks option switches.
- Supports DOS 2.x and 3.x programs that deallocate their
environment and place a smaller environment (containing
just the program name) in their own primary allocation block.
- Displays all selected primaries; previous versions would
display (e.g.) only the kernel if /k was selected.
- Fixes a problem that caused some deivces to show negative

Version 2.03
Fixes a problem in displaying disconnected high-memory chains
and resident programs loaded there.

Version 2.02
- Fixes a problem with the "largest conventional free block".
- Fixes problems with sizes of certain device drivers.
- Fixes problem with stack size display when "STACKS=0,0".
- Doesn't show the DOS data area as "unallocated".
- Increases the maximum allowable number of files, buffers, and
FCBs to 255 each (from 100).
- Reduces chance of displaying spurious high memory chains.
- Displays name field of environment (/E switch) only if all
characters in the field are in the displayable ASCII range
- Displays name field in raw display only if the field contains
an 8-character, blank-filled, displayable ASCII string, and
only if the block owns itself (implying that it's a program).
- Shows segment address of environment (/E switch).

Version 2.01 (6/7/90)
Fixes a problem that prevented PMAP from working on systems
with no expanded memory.

Version 2.00 (6/5/90)
- Attempts to identify disconnected high-RAM chains
- Adds /F (files) option
- Adds /E (environment) option
- Adds /K (kernel display) option and identifies areas of the
DOS data block used for files, buffers, stacks, etc.
- Adds /Q (quick display) option
- Supports permanent options via PMAP variable
- Correctly reports size of last installed device driver
- Supports altered switch characters
- Shows program name in raw display if available from
- Uses correct number of available file handles with extended
handle tables (old versions assumed 20 handles)

Version 1.34 (11/15/88)
Fixes a bug in 1.33 for resident programs that release their
environments under DOS 4.0.

Version 1.33 (11/14/88)
Uses a new feature of DOS 4.0 to more reliably obtain names of
resident programs, including those installed via INSTALL.

Version 1.31/1.32 (7/29/88)
Displays number of open handles for each PSP.
Displays sizes of some devices (/V switch).
Improved display when too many vectors to fit on one line.
Fixed spurious errorlevel returned by successful run (32).

Version 1.30
Adds /X, /S, and /? switches.
Adds device driver display (/V).
Displays names of EMS-users when available (LIM 4.0 only).
Allows wildcards in program-list.
Fixes problem with name of secondary copies of COMMAND.COM
under DOS 3.3 (it's not available).

Version 1.26
Corrects a problem detecting extended memory with certain
versions of BIOS ROM.

Version 1.25
Adds the extended memory display and the selective display

Corrects a minor problem with DOS 3.3.

Version 1.21
Bug fixes to version 1.20:

1. No more runaway display when EMS memory is present but none
of it is in use.

2. PMAP is more careful about what it thinks is the name of the
command shell.

This document and the program file PMAP.EXE ("the software") are
copyrighted by the author. The copyright owner hereby licenses
you to: use the software; make as many copies of the program and
documentation as you wish; give such copies to anyone; and
distribute the software and documentation via electronic means.
There is no charge for any of the above.

However, you are specifically prohibited from charging, or
requesting donations, for any such copies, however made; and
from distributing the software and/or documentation with
commercial products without prior permission. An exception is
granted to not-for-profit user's groups, which are authorized to
charge a small fee (not to exceed $7) for materials, handling,
postage, and general overhead. NO FOR-PROFIT ORGANIZATION IS


There is no restriction on the use of this software in
commercial or institutional environments.

No copy of the software may be distributed or given away without
this document; and this notice must not be removed.

There is no warranty of any kind, and the copyright owner is not
liable for damages of any kind. By using this free software,
you agree to this.

The software and documentation are:

Copyright (C) 1986, 1987, 1988, 1990 by
Christopher J. Dunford
The Cove Software Group
P.O. Box 1072
Columbia, Maryland 21044

(301) 992-9371
CompuServe 76703,2002 [IBMNET]

 January 4, 2018  Add comments

Leave a Reply