My program generates an error (2001). How do I tell what's going on?
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.
Exceptions that the kernel may trap include the following interrupts:
00h - divide by zero 01h - debug exception 03h - breakpoint 04h - overflow 05h - bounds 06h - invalid opcode 07h - device not available 08h - double fault 09h - overrun 0Ah - invalid TSS 0Bh - segment not present 0Ch - stack fault 0Dh - general protection fault 0Eh - page fault 10h - coprocessor errorThe 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-> DOS/4G error (2001): exception 0Eh (page fault) at 170:0042C1B2 2-> TSF32: prev_tsf32 67D8 3-> SS 178 DS 178 ES 178 FS 0 GS 20 EAX 1F000000 EBX 0 ECX 43201C EDX E ESI E EDI 0 EBP 431410 ESP 4313FC 4-> CS:IP 170:0042C1B2 ID 0E COD 0 FLG 10246 CS= 170,USE32,page granular, limit FFFFFFFF, base 0, acc CF9B SS= 178,USE32,page granular, limit FFFFFFFF, base 0, acc CF93 DS= 178,USE32,page granular, limit FFFFFFFF, base 0, acc CF93 ES= 178,USE32,page granular, limit FFFFFFFF, base 0, acc CF93 FS= 0,USE16,byte granular, limit 0, base 15, acc 0 GS= 20,USE16,byte granular, limit FFFF, base 6AA0, acc 93 5-> CR0: PG1:1 ET:1 TS:0 EM:0 MP:0 PE:1 CR2: 1F000000 CR3: 9067 6-> Crash address (unrelocated) = 1:000001B2 7-> Opcode stream:8A 18 31 D2 88 DA EB 0E 50 68 39 00 43 E8 1D 8-> Stack: 0178:004313FC 000E 0000 0000 0000 C2D5 0042 C057 0042 0170 0000 0000 0000 0178:00431414 0450 0043 0452 0043 0000 0000 1430 0043 CBEF 0042 011C 0000 0178:0043142C C568 0042 0000 0000 0000 0000 0000 0000 F248 0042 F5F8 0042 0178:00431444 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0178:0043145C 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0178:00431474 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 9-> Last 4 ints: 21 @ 170:42CF48/21 @ 170:42CF48/21 @ 170:42CF48/E @ 170:42C1B2/
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 particluar 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.