PMAP 1.32 --------- PMAP (Program MAP) is a simple program that displays how your PC's memory is being used. It lists all active programs (including resident programs such as Sidekick and PCED) and tells you how much free memory is available for programs. If expanded (LIM) memory is present, a summary of EMS use is also shown. A list of installed devices is optionally displayed. | indicates new or changed features for the latest version of PMAP. See also version history below. Syntax summary -------------- The command line syntax of PMAP is: | pmap [/drsvx?] [program-list] The optional /switches are: d display Detail list of allocation by programs r display Raw list of memory blocks | s display only Standard DOS memory | v display deVice driver information | x display only eXpanded memory | ? display syntax summary Program-list, if present, restricts the display to the listed programs. Named programs may contain wildcards (*). Examples: pmap (default display) pmap /r (raw display) pmap /d sdump (detail display of program SDUMP only) pmap sdump c* (display SDUMP and anything beginning with C) pmap /x (display only expanded memory usage) pmap /v (display only device driver data) Standard display ---------------- When PMAP is invoked without parameters, you'll see a display 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 ... Total conventional free memory 4 451696 Largest conventional free block 371168 Extended memory installed 425984 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. 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 program. Vectors A list of 80x8x interrupt vectors that appear to have been "intercepted" by the program. For 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. 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. The amount of extended memory (AT memory above the 1 megabyte mark) is displayed only if such memory is present. You can restrict the display to certain programs by naming them on the command line. For example, pmap sdump ced would display information for the SDUMP and CED programs, and no others. The summary and expanded memory information is always displayed. | 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 its standard display. If you are interested to see how large it is and where it is allocated, use the /R display described below, in which it will be the first block listed; it will usually show 0008 in the "owner" field. Detail display -------------- When you run PMAP with the /D (Detail) parameter, 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. Raw display ----------- 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 [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 one. 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. If the /R switch is included, all other command line parameters are ignored. Expanded memory display ----------------------- If expanded (LIM-EMS, or EEMS) memory is present, PMAP always 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. If you only want to display the expanded memory allocation, use the /X switch. To suppress the display of expanded memory, use /S. | Device driver display | --------------------- | | 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 | fields: | | 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 inplies 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. 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. | | PMAP cannot determine the size of the last device loaded by | CONFIG.SYS. If you wish to determine the size of the last | device, and your CONFIG.SYS loads more than one device, you can | determine its size by simply swapping the load order of the last | two devices in CONFIG.SYS and rebooting. | | 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). 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, 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 COMMAND.COM. 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 the can execute COMMAND.COM and ask it to run the requested program. If the former, PMAP will show the true parent; if the latter, PMAP will show COMMAND.COM, 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. Finally, a "shell" exit was taken from QE, which did reload COMMAND.COM; notice that COMMAND shows as its own parent. | 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). | | 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 (it 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. DOS (version 2.00 or later) manages memory as a chain of "blocks". 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 3.30), 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 follows: 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-15 Reserved This structure provides all of the information needed to step through the memory allocation chain. A basic algorithm is as follows: 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, so abort Block_owner = word (MCB:1) Block_size = word (MCB:3) MCB = MCB + block_size + 1 End EMS and EEMS memory is not, of course, 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 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 option. 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. Copyright/License/Warranty -------------------------- 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 AUTHORIZED TO CHARGE ANY AMOUNT FOR DISTRIBUTION OF COPIES OF THE SOFTWARE OR DOCUMENTATION, OR TO INCLUDE COPIES OF THE SOFTWARE OR DOCUMENTATION WITH SALES OF THEIR OWN PRODUCTS. THIS INCLUDES A SPECIFIC PROHIBITION AGAINST FOR-PROFIT ORGANIZATIONS DISTRIBUTING THE SOFTWARE, EITHER ALONE OR WITH OTHER SOFTWARE, AND CHARGING A "HANDLING" OR "MATERIALS" FEE OR ANY OTHER SUCH FEE FOR THE DISTRIBUTION. NO FOR-PROFIT ORGANIZATION IS AUTHORIZED TO INCLUDE THE SOFTWARE ON ANY MEDIA FOR WHICH MONEY IS CHARGED. PERIOD. 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 by Christopher J. Dunford The Cove Software Group P.O. Box 1072 Columbia, Maryland 21044 (301) 992-9371 CompuServe 76703,2002 [IBMNET]