Recursive Batch File Loops in MS-DOS 6.22

This article explains how the MS-DOS 6.22 command interpreter, COMMAND.COM, manages execution loops triggered by recursive batch file calls. It examines the technical differences between direct file chaining and nested execution via the CALL command, detailing file pointer tracking, internal memory allocation, nesting depth limits, and the conditions that lead to system termination or crashes.

Direct Chaining vs. Nested Invocation

The behavior of a recursive batch file in MS-DOS 6.22 depends entirely on whether the script calls itself directly by name or uses the CALL command.

When a batch file invokes itself directly (for example, RECURSE.BAT executing the line RECURSE without CALL), COMMAND.COM treats this as a transfer of control rather than a subroutine. The shell terminates the current batch context and initiates a new one from the beginning of the file. No return address is saved, and no stack frame is allocated. This mechanism is essentially a jump operation. Because memory structures are overwritten rather than nested, a direct recursive call can run indefinitely without exhausting conventional memory, forming an infinite loop that can only be interrupted by the user pressing Ctrl+C or Ctrl+Break.

Nested Execution with the CALL Command

When recursion is initiated using the CALL command (such as CALL RECURSE.BAT), COMMAND.COM treats the operation as a nested subroutine that must eventually return execution to the line following the invocation.

To achieve this, COMMAND.COM maintains an internal batch context block for every active nesting level. This block preserves:

  • The full file path of the calling batch file.
  • The file seek offset pointing to the next line to be executed upon return.
  • Any active redirection states and command-line arguments.

Because each CALL allocates another context block, this method does not execute in constant space. Instead, it systematically consumes memory within the interpreter's internal structures.

Memory Limitations and Stack Exhaustion

Unlike modern command-line interpreters that support thousands of recursion levels, MS-DOS 6.22 operates within the strict boundaries of conventional memory (the first 640 KB of RAM) and uses a hardcoded batch nesting limit.

COMMAND.COM in version 6.22 allocates a fixed table for nested batch processing. Once the recursive loop exceeds the maximum supported nesting depth, the command interpreter fails to allocate a new batch context. At this threshold, MS-DOS typically displays an error message such as Out of environment space or simply halts execution because it cannot allocate the required internal tracking structures.

If free conventional memory is severely constrained before reaching the software limit, recursive calls may fail earlier due to low-memory conditions, corrupting the transient portion of COMMAND.COM or destabilizing the operating system entirely.

File Pointer and Disk I/O Mechanics

MS-DOS 6.22 does not load batch files entirely into RAM. To minimize memory usage, COMMAND.COM parses batch files line by line directly from the storage media.

In a recursive loop:

  1. The shell reads a line from the storage device.
  2. It records the file offset pointer.
  3. Upon processing a recursive call, it opens a handle or re-seeks the file back to byte zero.
  4. With the CALL command, every level of recursion preserves its respective seek offset on the internal stack.

Because the operating system constantly reads the file from disk or floppy drive during each cycle of the recursion, execution speed is heavily throttled by physical I/O latency. In rapid recursive loops running on floppy-based systems or slow hard drives, this behavior results in constant disk drive head activity until the recursion is manually halted or runs out of resources.