DOS/4G and DOS/4GW FAQ:Interpreting Error 2001

Error 2001 is of the form: exception <exception_number> at
<address>. The address listed is usually that of the faulting
instruction, but in some cases, the address will correspond to the next
instruction in the code after the faulting instruction.

The error message is followed by a dump that shows the contents of all
of the CPU registers at the point of the exception.

If the DOS4G option CrashVerbose is not already set to ON, set the
option. This will cause the kernel to print out more information when
your program crashes. Then run the program again. Completing the
following steps will help you find the problem that caused the crash.

1. Record all of the information from the register dump.

2. Determine the circumstances under which the error occurs.

3. Consult you debugger manual, or an Intel 80x86 Programmer's
Reference manual, to determine the circumstances under which
the processor will generate the reported exception.

4. Get the program to fail under your debugger, which should stop the
program as soon as the exception occurs.

5. Determine from the exception context why the processor generated
an exception in this particular instance.

This sample register dump shows the kind of information the kernel
displays when CrashVerbose=ON.

1. The error message includes a synopsis of the problem. In this case,
the processor signaled a page fault (0Eh) while executing at address
170:0042C1B2.

2. The prev_tsf field is not usually of interest.

3. These are the register values at the time of the exception. The
kernel also displays the interrupt number and error code (pushed on
the stack by the processor for certain exceptions).

4. The kernel describes the descriptors referenced by each segment
register, for your convenience. In general, USE32 segments belong
to your program; USE16 segments generally belong to the DOS extender.
Here, CS points to your program's code segment, and SS, DS, and ES
point to your data segment. FS is null, and GS points to a DOS
extender code segment.

5. The control register information is not of any general interest,
except on a page fault, when CR2 contains the address value that
caused the fault. Since EAX in this case contains the same value,
an attempt to dereference EAX could have caused this particular
fault.

6. The crash address (unrelocated) tells you where the crash occurred
relative to your program's link map. This allows you to know where
the crash occurred even if you can't reproduce the crash in a
debugger.

7. The opcode stream shows the next 16 bytes from the code segment at
the point of the exception. If you disassemble these bytes, you can
tell what instructions caused the crash even without using a debugger.
In this case, 8A 18 is the instruction mov bl, [eax].

8. The Stack: section shows 72 words from the top of the stack.
You may recognize function calls or data from your program
on the stack.

9. The kernel then lists the last four interrupts that it handled in
protected mode, in chronological order (last interrupt listed last).
In this example, the last interrupt issued before the page fault
occurred was an Interrupt 21h at address 170:42CF48. This information
may provide helpful context.