How HIMEM.SYS Reports Extended Memory in MS-DOS

In MS-DOS 6.22, available extended memory is calculated through a multi-stage process where the default Extended Memory Specification (XMS) driver, HIMEM.SYS, queries system firmware at boot, manages physical RAM above the 1 MB boundary, and exposes dedicated software interrupt functions to report memory statistics. Utilities like MEM.EXE communicate directly with the HIMEM driver interface rather than querying hardware directly, allowing the operating system to accurately compute total, allocated, and free extended memory blocks.

Step 1: Hardware Detection at Boot

When HIMEM.SYS loads via CONFIG.SYS, it identifies physical memory installed above the 1 MB real-mode boundary by querying the system BIOS:

  • INT 15h, Function 88h: The standard AT BIOS call to detect contiguous extended memory. This call returns the amount of continuous memory above 1,024 KB in kilobytes (stored in the AX register), limited historically to 64 MB.
  • INT 15h, Function E801h or E820h: Supported on newer 80486 and Pentium-era BIOS implementations available during the MS-DOS 6.22 era to detect memory spaces exceeding 64 MB.

Once the physical memory boundaries are mapped, HIMEM takes control of the A20 address line, reserves the first 64 KB block above 1 MB as the High Memory Area (HMA), and constructs internal Extended Memory Block (EMB) descriptor tables to track allocations.

Step 2: Establishing the XMS Driver Entry Point

Applications and DOS utilities do not communicate with HIMEM via standard software interrupts directly. Instead, they obtain a direct far-call entry point:

  1. The program executes Interrupt 2Fh with register AX = 4300h to verify if an XMS driver is installed. A return of AL = 80h confirms presence.
  2. The program requests the driver's API entry-point address using Interrupt 2Fh with register AX = 4310h.
  3. HIMEM.SYS returns the memory address of its control function in the ES:BX registers. All subsequent memory calculations are performed by making a FAR CALL to this address.

Step 3: HIMEM.SYS Reporting Calls

To calculate available extended memory, caller programs set the AH register to specific function codes before executing the far call to the XMS entry point:

Function 08h: Query Free Extended Memory (XMS 2.0)

This standard 16-bit reporting call is used for systems addressing up to 64 MB of RAM:

  • Input: AH = 08h
  • Output:
    • AX = Size of the largest free extended memory block (in KB).
    • DX = Total amount of free extended memory (in KB).
    • BL = Error status code (if operation fails).

Function 88h: Query Any Free Extended Memory (XMS 3.0)

MS-DOS 6.22 ships with HIMEM.SYS version 3.09+, which supports 32-bit registers to calculate memory on systems with more than 64 MB of RAM:

  • Input: AH = 88h
  • Output:
    • EAX = Size of the largest free extended memory block (in KB).
    • EDX = Total amount of free extended memory (in KB).
    • ECX = Highest physical memory address available.
    • BL = Error status code.

Step 4: The Internal Accounting Formula

When Function 08h or Function 88h is called, HIMEM.SYS parses its internal handle table. Each handle stores a base address, a block length, and an allocation state (free or in-use).

HIMEM calculates the total available extended memory using the following logic:

  1. Total Managed Memory: The sum of all contiguous physical RAM identified at boot minus memory reserved for internal descriptors.
  2. HMA Subtraction: If DOS=HIGH is specified in CONFIG.SYS, the 64 KB High Memory Area is isolated and managed separately; it is not counted in the free extended pool.
  3. Handle Traversal: HIMEM scans all unallocated EMB handles. It sums their sizes to produce the value for DX/EDX (total free extended memory) and identifies the single contiguous unallocated handle with the highest size value to place into AX/EAX (largest free block).

Step 5: Presentation in MS-DOS Utilities

When a user runs the MEM command in MS-DOS 6.22, the utility queries HIMEM using Function 88h (falling back to Function 08h if 32-bit calls are unsupported). MEM.EXE takes the value returned in EDX, converts the kilobyte count to bytes, and combines it with handle information to output the exact distribution of total, used, and free XMS memory.