How MS-DOS 6.22 MEM Checks Memory Residency

The MS-DOS 6.22 MEM utility analyzes system memory residency by querying internal DOS structures to walk the chain of Memory Control Blocks (MCBs), inspect Program Segment Prefixes (PSPs), and traverse system device driver headers. Rather than monitoring active execution, MEM.EXE reconstructs a static snapshot of resident programs, drivers, and Upper Memory Blocks (UMBs) by interpreting the memory arena headers linked throughout conventional and high memory.

Locating the System Arena via the List of Lists

To begin its evaluation, MEM.EXE must locate where usable memory begins. It does this by issuing an undocumented DOS system call: Interrupt 21h, Function 52h (Get List of Lists, also known as SYSVARS).

The pointer returned by this interrupt contains references to critical DOS internal variables:

  • A pointer to the first conventional Memory Control Block.
  • The head of the system device driver chain.
  • Pointers to open file tables and drive parameters.

By retrieving the address of the first MCB from the List of Lists, MEM establishes the starting point for traversing conventional memory (the first 640 KB).

Traversing the MCB Chain

MS-DOS manages contiguous memory using MCBs (also referred to as arena headers). Each MCB occupies exactly one paragraph (16 bytes) immediately preceding the memory block it describes:

  1. Signature Byte (Offset 00h): Holds an ASCII 'M' (4Dh) to indicate a standard linked block, or 'Z' (5Ah) to mark the final block in the chain.
  2. Owner Field (Offset 01h): A 16-bit segment address pointing to the PSP of the program that owns the allocation.
  3. Size Field (Offset 03h): A 16-bit integer defining the size of the allocated block in 16-byte paragraphs.
  4. Reserved/Name Field (Offset 08h): In DOS 4.0 and higher, including 6.22, bytes 08h through 0Fh contain an 8-character ASCII string representing the program name.

MEM.EXE reads the first MCB, records the owner and size, and calculates the address of the next MCB by adding the block's paragraph count plus one (for the header itself) to the current segment address. It repeats this process until it encounters the 'Z' delimiter.

Resolving Resident Programs and TSRs

When traversing the MCB chain, MEM determines the nature of each resident block by examining the Owner field:

  • Free Memory: An owner value of 0000h designates an unallocated block.
  • Operating System Segments: An owner value of 0008h indicates memory reserved by DOS system data or device drivers.
  • Program/TSR Memory: If the owner address matches the segment of the memory block directly following the MCB, the block contains a Program Segment Prefix (PSP), identifying a primary executable or Terminate and Stay Resident (TSR) program.
  • Environment and Secondary Blocks: If the owner points elsewhere in memory, the block represents auxiliary storage, such as an environment block, data buffer, or sub-allocation associated with a resident program.

To verify executable authenticity, MEM reads the target PSP at offset 00h to check for the standard DOS exit instruction (CD 20h or INT 20h). It then inspects the PSP’s environment segment (located at offset 2Ch) to parse the program’s full path and filename if the 8-byte MCB name field is unpopulated.

Scanning Device Drivers

Device drivers loaded via CONFIG.SYS bypass standard PSP-based program execution. To track their residency, MEM traverses the device driver chain located in the List of Lists.

Each device header points to the next via a standard far pointer (offset 00h). MEM reads the driver attributes, determines whether it is a character or block device, extracts the device name, and matches the driver's memory segment to the surrounding MCB allocations.

Querying Upper Memory Blocks (UMBs) and XMS

For systems running HIMEM.SYS and EMM386.EXE, MEM.EXE inspects upper memory (between 640 KB and 1 MB):

  1. XMS Driver Detection: MEM calls Interrupt 2Fh, Function 4300h to verify the presence of an Extended Memory Specification (XMS) manager.
  2. UMB Chain Query: If UMB support is active, MEM links upper memory blocks into its residency check. DOS 6.22 links UMBs into the main MCB chain or treats them as secondary MCB chains managed via internal sub-functions (Interrupt 21h, Function 58h, sub-functions 02h and 03h to get/set UMB link status).
  3. High Memory Area (HMA): MEM issues standard XMS calls (Interrupt 2Fh, Function 4310h) to report whether DOS itself or another driver is resident in the 64 KB High Memory Area.

Formatting the Output

Once the traversal routines gather the sizes, types, and names of all active segments, MEM.EXE aggregates the data based on user flags:

  • Default: Summarizes total conventional, upper, and extended memory along with largest executable program sizes.
  • /C (Classify): Groups memory blocks by executable name, totaling conventional and UMB allocations.
  • /D (Debug): Outputs a raw, sequential breakdown of every MCB, internal device driver segment, and empty hole in memory.
  • /M (Module): Filters the traversal to display only allocations and sub-allocations owned by a specific resident program.