home *** CD-ROM | disk | FTP | other *** search
- MemMap: Map of DOS Memory Blocks
- Using Turbo Pascal 5.0
-
- by
-
- Earl F. Glynn
- Overland Park, KS
- CompuServe 73257,3527
-
- (C) Copyright 1989, All Rights Reserved.
-
-
- Introduction
- ------------
-
- MemMap is a DOS utility that displays all allocated memory blocks,
- including terminate-and-stay-resident (TSR) programs and their
- associated environment memory blocks. With a /V switch, MemMap
- displays the variables in each environment block.
-
- MemMap has been tested with DOS 2.10, 3.3, 4.0 and OS/2 Extended Edition
- 1.1 DOS Command subset.
-
- The original motivation for writing MemMap was to determine the amount
- of memory lost to needless environment variables being saved every time
- a TSR was loaded into memory. But several other factors shaped the
- development of MemMap:
-
- - DOS 4.0 "MEM /DEBUG" functionality is not present in DOS 3.X.
- Some utilities, such as PC Magazine's PCMAP, give part of the
- information desired about TSRs.
-
- - PCMAP returns "unknown" for most program names when run under
- DOS 4.0 (See Figure 1). Since MEM is a new command under
- DOS 4.0, and cannot be run on earlier DOS versions, a common
- program that operates under both DOS 3.X and 4.X is desirable.
-
- - DOS 4.0 MEM reports block sizes only in hexadecimal bytes, e.g.,
- Sidekick (SKM) is hex 7180 bytes long, instead of decimal
- 29056 bytes.
-
- - PCMAP aggregates both environment and program blocks, creating
- two problems: (1) the memory entries are not always listed
- in ascending order; (2) size information about individual
- environment blocks is not available.
-
- - The size and contents of the environment blocks cannot be
- effectively managed without an easy way to display all variables
- in all environment blocks.
-
- - Several memory map programs have erratic behavior when IBM's
- Workstation Program (INDCIPL.EXE) and Expanded Memory
- Manager (INDXMAA.SYS) are in memory.
-
- - Turbo Pascal can be used to write system utilities as easily
- as assembly language or C. In particular, MemMap demonstrates
- the ability of Turbo Pascal to manipulate DOS system control
- blocks using pointer variables and record types.
-
-
- Background
- ----------
-
- The layout of DOS user memory is shown in Figure 2. Following the DOS
- system area, each memory block is preceded by a memory control block
- (MCB). This MCB stores information on the owner of the block and
- the size of the memory block -- described in Figure 3. Once the
- initial MCB is found, the next MCB follows the memory block. All
- of user memory can be mapped by stepping through, MCB by MCB. The last
- MCB is tagged differently than all other MCBs, so a termination condition
- is easily recognized. But how is the address of the first MCB found?
-
- The first Memory Control Block can be found by searching through
- memory at paragraph boundaries, or by using the undocumented function
- call $52 of DOS interrupt $21. MemMap uses the latter approach
- to obtain the address of the so-called DOS "List of Lists". At an offset
- of -2 in this "List of Lists" is the segment address of the first MCB.
-
- The "Type" of an MCB is determined by observing when certain relationships
- exist. If the MCB owner is hex 0000, the block following the MCB is
- not allocated and its type is shown as "Free Space". When the first
- word of the paragraph following the MCB is hex 20CD (or possibly
- 27CD), the block type is "Program", if the "owner" field points
- to this next paragraph; otherwise, the "owner" is assumed to be the DOS
- kernel and the block type is shown as "System". See Figure 4. The block
- type is "Environment" when the block's owner has an environment pointer
- back to the paragraph following the MCB. When none of the above
- relationships hold, the block is assumed to have a "Data" type. (One
- TSR that I've found with a "Data" memory block is PC Magazine's
- PRN2FILE).
-
- The "Name" of an MCB is determined from the environment block when
- possible. In DOS 3.X, the fully-qualified program name follows the
- environment value(s) and a special tag word (hex 0001), as shown in
- Figure 4. When an environment block does not exist for a program,
- or when the program name does not follow the environment block,
- a "short" program name (1-8 characters) can be found in the last
- half of the MCB -- but only in DOS 4.0. In earlier DOS versions
- the name is "<unknown>" in such a case.
-
-
- Implementation Details for Turbo Pascal 5.0
- -------------------------------------------
-
- Pointers are usually used to address dynamic variables created with
- the standard Pascal NEW procedure (or Turbo Pascal's GetMem procedure),
- but pointers can also be used to manipulate existing data structures,
- such as DOS memory blocks. An example of accessing DOS's "List of Lists",
- Memory Control Blocks (MCBs) and the Program Segment Prefix (PSP) blocks
- using pointer variables is shown in the MemMap Turbo Pascal 5.0 program.
- (See Figure 5).
-
- To obtain the address of the DOS "List of Lists", the undocumented
- function call $52 of DOS interrupt $21 is needed. The DOS Turbo Pascal
- UNIT provides the "Intr" procedure and "Registers" type:
-
- ...
-
- VAR r: Registers; {Figure 5, line 57}
- ...
-
- r.AH := $52; {line 205}
- Intr ($21,r); {line 206}
-
- After this DOS interrupt, a pointer to the "List of Lists" is in ES:BX.
- At an offset of -2 in the "List of Lists" is the segment address of the
- first MCB:
-
- segment := MemW[r.ES:r.BX-2]; {line 207}
-
- where the "MemW" Turbo Pascal "system array" returns the word at the
- given segment:offset address. The "MCB" pointer variable is then
- defined using the Turbo Pascal "Ptr" procedure:
-
- MCB := Ptr(segment,0); {line 210}
-
- At this point all the variables defined by the MemoryControlBlock TYPE
- can be accessed. Typecasting can be used to help calculate the size of
- the memory block following the MCB:
-
- bytes := LongInt(MCB^.BlockSize) SHL 4; {line 102}
-
- If the MCB^.BlockOwner is zero, the block is free space. If it is
- nonzero, the MCB^.BlockOwner points to a memory block, which is a
- valid Program Segment Prefix (PSP) if it starts with the word $20CD
- (or possibly $27CD). The PSP pointer is defined by
-
- psp := Ptr(MCB^.BlockOwner,0); {line 109}
-
- A segment pointer to the environment block is at an offset of hex 2C from
- the beginning of the PSP, which is defined by psp^.Environment.
- Since the environment block must be immediately preceded by an MCB, the
- environment MCB is defined by:
-
- MCBenv := Ptr(psp^.Environment-1,0); {line 116}
-
- If the MCB^.BlockOwner is the same as the MCBenv^.BlockOwner,
- environment variables follow in ASCIIZ delimited strings (character
- strings ending with a $00). A null (zero-length) variable marks the
- end of the environment. The program name follows the special
- $0001 tag.
-
- Once an MCB and its associated information is displayed, the segment
- address of the next MCB is found by the statement:
-
- segment := segment + MCB^.Blocksize + 1; {line 212}
-
- The extra "1" above is needed since the MCB is itself a single
- paragraph long.
-
- Contiguous MCBs and memory blocks can be sequentially listed until
- the last MCB is found, which is tagged with MCB^.Blocktag = $5A.
-
- A final note: DO NOT use DISPOSE (or FreeMem) to deallocate
- a pointer variable that was not allocated using NEW (or GetMem).
- Since the DOS control blocks described above are allocated outside
- of MemMap, they should not be deallocated by MemMap.
-
-
- Results
- -------
-
- To demonstrate MemMap, several DOS commands and other TSRs were executed
- to create a variety of memory control blocks (after booting without
- an AUTOEXEC.BAT or CONFIG.SYS present):
-
- APPEND ..
- GRAPHICS
- MODE LPT1=COM1
- \TSR\DOSED
- \PCMAG\INSTALL
- \PCMAG\CAPTURE
- \PCMAG\CONFIRM
- \PCMAG\PRN2FILE
- \PCMAG\PUSHDIR
- \PCMAG\POP-CAL
- \SIDEKICK\SKM
-
- Figure 6 shows MemMap's output from PC DOS 3.3. Note that the name of
- several programs cannot be determined, namely the MCB at 103E (CAPTURE),
- 1190 and 1200 (PRN2FILE) and 1301 (PUSHDIR). With the same set of TSRs
- loaded with DOS 4.0, Figure 7 shows the "short" 1-8 character names of
- all programs "unknown" to DOS 3.3, since these names were stored in the
- block owner's MCB. For comparison, the output from the DOS 4.0
- "MEM /DEBUG" command is shown in Figure 8.
-
- The contents of the environment blocks can be determined using the /V
- switch of MemMap. Figure 9 shows the output of "MEMMAP /V".
- Note in Figure 9 that OS/2 EE 1.1 DOS subset reports itself as
- DOS 10.10. But the MemMap listing for OS/2 DOS subset is more like
- DOS 3.3 than DOS 4.0.
-
- The current environment variables maintained by DOS are in the first
- environment block with a name of "<shell>". The size of this first
- block is 160 bytes in Figures 6 and 7 since this is the default
- environment size. The size of this first environment block can be
- increased by adding a statement to the CONFIG.SYS (and re-booting).
- For example, to increase the environment space to 512 bytes, add the
- following to CONFIG.SYS:
-
- SHELL=\COMMAND.COM /P /E:512
-
- In addition to the working set of environment variables set up at
- boot time, DOS makes a copy of the variables in effect at the time a
- TSR is loaded. The size of each of these environment blocks is
- adjusted to accommodate only the variables set at the time the TSR
- is loaded. This is why DOS 3.3 shows 10 environment blocks (Figure 6)
- and DOS 4.0 shows 7 environment blocks (Figure 7). Apparently,
- the DOS 4.0 commands APPEND, GRAPHICS and MODE are now "smart" enough
- not to make copies of the environment variables.
-
- Inspection of output using "MEMMAP /V" results in a few "rules" to
- minimize unnecessary, wasted memory:
-
- 1. Load TSRs with the smallest possible set of environment
- variables in effect. If possible, reduce the set to COMSPEC
- and a very short PATH.
-
- 2. In AUTOEXEC.BATs, load TSRs before PATH or SETs, if possible.
- Use fully-qualified names to load TSRs so the PATH can be
- reduced.
-
- 3. Never re-execute AUTOEXEC.BAT after bootup, if it contains TSRs
- that re-install themselves multiple times. Many TSRs do not
- check to see if they are already resident. MemMap can quickly
- determine when a TSR is loaded into memory multiple times.
-
- Even when these "rules" are followed in loading TSRs, Figure 6
- shows 576 bytes lost to environment blocks -- not counting the 160-byte
- boot-time "current" environment block. Hundreds of bytes can be lost
- to needless copies of environment variables if care is not taken.
-
-
- A Memory Enigma
- ---------------
-
- The IBM 3270 Workstation Program (INDCIPL.EXE) allows mainframe host "sessions"
- and PC "sessions" with a hotkey between them. Depending on how INDCIPL is
- configured, DOS conventional memory can be very limited, even when the
- IBM Expanded Memory Manager (INDXMAA.SYS) is used.
-
- The state of DOS conventional memory from a PC session under INDCIPL
- is shown in Figure 10 from both PCMAP and MemMap. Note both programs
- report a large number of null MCBs -- MCBs pointing to zero-length
- memory blocks. The reason the two programs are not consistent, and
- the reason why only a portion of conventional memory appears to be
- available has not yet been explained. This should not be surprising
- since much "undocumented" information is used by PCMAP and MemMap.
- Information about MCBs is not in the IBM DOS 3.3 Technical Reference
- Manual, but rather books such as "The Waite's Group MS-DOS Developer's
- Guide".
-
- These null MCBs appear to be a trick to reserve large memory chunks
- and make them unavailable to "normal" DOS applications. In the two
- MemMap cases shown in Figure 10, a 51K chunk and a 312K chunk of memory
- are taken up with consecutive null MCBs that appear to be placeholders.
-
-
- Summary
- -------
-
- MemMap demonstrates Turbo Pascal can easily manipulate DOS control
- blocks using pointer variables and record types. MemMap has 215 Pascal
- lines and creates a 6128-byte EXE file. By contrast, PCMAP has 300
- assembly language statements and creates a 643-byte COM file (stored
- in a 2048-byte cluster on most hard disks). While certain efficiencies
- are lost in a high-level language, like Pascal, when writing system
- utilities, often the maintainability is much easier in the high
- level language. Besides, it's not difficult to improve on certain
- DOS components, such as the PC DOS 4.0 MEM command: MEM is a 20133-byte
- EXE file -- more than 3 times larger than the MEMMAP.EXE program.