How MS-DOS 6.22 Executes COM and EXE Files

MS-DOS 6.22 handles the execution of COM and EXE files using distinct loading mechanisms tailored to their differing internal architectures. COM files are simple, flat memory images constrained to a single 64KB segment, while EXE files are structured, relocatable executables capable of spanning multiple segments up to the limit of available conventional memory. When launching a program, DOS determines the file type, allocates memory, builds a Program Segment Prefix (PSP), sets the CPU registers to specific initial states, and hands execution over to the application.

File Identification and Priority

When a user enters a command without an extension, MS-DOS 6.22 searches the current directory and PATH in a strict order:

  1. Internal commands (e.g., DIR, COPY)
  2. .COM files
  3. .EXE files
  4. .BAT files

Although the extension guides file discovery, MS-DOS does not rely solely on the extension to determine the internal file format. Upon opening the file, the operating system reads the first two bytes. If these bytes match the ASCII characters "MZ" or "ZM" (0x4D 0x5A or 0x5A 0x4D, named after MS-DOS engineer Mark Zbikowski), MS-DOS processes the file as an EXE format executable, even if it carries a .COM extension. If the signature is absent, the file is treated as a flat COM binary.

Loading and Executing COM Files

The COM (Command) format is a direct carryover from CP/M-80, designed for simplicity and small memory footprints. It contains no file header, relocation data, or metadata—only raw, executable x86 machine code.

  1. Memory Allocation: MS-DOS 6.22 allocates a memory block for the COM file. By default, it allocates all available conventional memory in the largest free block (or up to 64KB if restricted), though the code, data, and stack combined cannot exceed 64KB. Because the file must fit inside a single segment alongside its overhead, the maximum size of a COM file on disk is roughly 65,280 bytes.
  2. Program Segment Prefix (PSP): DOS constructs a 256-byte (100h bytes) PSP at the base of the allocated segment. The PSP contains the exit address, interrupt vectors, the Command Line Parameter table, and the File Handle Table.
  3. Binary Image Loading: The entire contents of the COM file are read directly from disk into memory, beginning immediately after the PSP at offset 0100h.
  4. Register Initialization:
    • CS, DS, ES, SS: All four segment registers are set to point to the base segment containing the PSP.
    • IP (Instruction Pointer): Set to 0100h, pointing to the start of the loaded program code.
    • SP (Stack Pointer): Set to the end of the 64KB segment (usually FFFEh), providing a working stack that grows downward toward the program code. If the segment is smaller than 64KB, SP is placed at the end of the allocated block.
    • A zero word (0000h) is pushed onto the stack, allowing a simple near return (RET) instruction to trigger a jump to PSP offset 0000h (which contains an INT 20h instruction to exit back to DOS).
  5. Transfer: Control transfers directly to CS:0100h.

Loading and Executing EXE Files

The EXE format (specifically the DOS MZ executable format) supports programs that require more than 64KB of memory, separating code, data, and stack into distinct segments.

  1. Header Parsing: MS-DOS reads the minimum 512-byte header at the start of the file. The header contains:
    • The "MZ" signature.
    • The program size and header size.
    • Relocation table offset and entry count.
    • Minimum and maximum memory requirements (MINALLOC and MAXALLOC).
    • Initial register values for CS:IP and SS:SP.
  2. Memory Allocation: DOS allocates a block of memory sized to fit the PSP, the load module, and at least the minimum extra paragraphs defined in MINALLOC.
  3. PSP Creation: DOS places a 256-byte PSP at the beginning of the allocated block.
  4. Image Loading: The program code and data (the load module) are loaded immediately above the PSP.
  5. Relocation Processing: Because an EXE can be loaded at any arbitrary segment in memory, any hardcoded segment references within the code must be patched. DOS reads the relocation table from the EXE header, iterates through each pointer entry, and adds the base segment address of the load module to the word at each specified offset.
  6. Register Initialization:
    • DS and ES: Point to the segment of the PSP, allowing the application to read command-line arguments and DOS environment data. The application is responsible for changing DS and ES to its own data segments if needed.
    • CS:IP: Loaded with the initial values from the EXE header, with the load module base segment added to the header's CS value.
    • SS:SP: Loaded with the initial values from the EXE header, with the load module base segment added to the header's SS value.
  7. Transfer: MS-DOS transfers execution via a far jump or far call to the calculated initial CS:IP.