Browse Source

+ added division by zero exception handling for i8086-msdos

git-svn-id: trunk@26073 -
nickysn 11 years ago
parent
commit
06c5acf69a
2 changed files with 114 additions and 0 deletions
  1. 107 0
      rtl/msdos/prt0stm.asm
  2. 7 0
      rtl/msdos/system.pp

+ 107 - 0
rtl/msdos/prt0stm.asm

@@ -31,6 +31,10 @@
         extern __nearheap_start
         extern __nearheap_start
         extern __nearheap_end
         extern __nearheap_end
 
 
+        extern __SaveInt00
+
+        extern FPC_HANDLEERROR
+
 %ifdef __TINY__
 %ifdef __TINY__
         resb 0100h
         resb 0100h
 %endif
 %endif
@@ -175,6 +179,109 @@ error_msg:
         mov ax, 4CFFh
         mov ax, 4CFFh
         int 21h
         int 21h
 
 
+FPC_INT00_HANDLER:
+        sub sp, 4  ; reserve space on the stack for the retf
+
+        push bx
+        push cx
+        push ds
+
+        ; init ds
+%ifdef __TINY__
+        mov bx, cs
+%else
+        mov bx, dgroup
+%endif
+        mov ds, bx
+
+        ; check whether we're running on the same stack
+        mov cx, ss
+        cmp bx, cx
+        jne .call_previous_handler
+
+%ifndef __MEDIUM__
+        ; check whether we're coming from the same code segment
+        mov bx, sp
+        mov cx, [bx + 3*2 + 6]  ; get caller segment
+        mov bx, cs
+        cmp bx, cx
+        jne .call_previous_handler
+%endif
+
+        ; runerror 200
+        mov bx, sp
+        mov cx, [bx + 3*2 + 4]  ; get caller offset
+%ifdef __MEDIUM__
+        mov dx, [bx + 3*2 + 6]  ; get caller segment
+%endif
+        add sp, 3*2 + 4 + 6
+        xor ax, ax
+        push ax
+        mov ax, 200
+        push ax
+%ifdef __MEDIUM__
+        push dx
+%endif
+        push cx
+        jmp FPC_HANDLEERROR
+
+.call_previous_handler:
+        mov bx, sp
+        mov cx, [__SaveInt00]
+        mov [ss:bx + 3*2], cx
+        mov cx, [__SaveInt00+2]
+        mov [ss:bx + 3*2 + 2], cx
+        pop ds
+        pop cx
+        pop bx
+        retf  ; jumps to the previous handler with all registers and stack intact
+
+
+
+        global FPC_INSTALL_INTERRUPT_HANDLERS
+FPC_INSTALL_INTERRUPT_HANDLERS:
+        push ds
+
+        ; save old int 00 handler
+        mov ax, 3500h
+        int 21h
+        mov [__SaveInt00], bx
+        mov bx, es
+        mov [__SaveInt00+2], bx
+
+        ; install the new int 00 handler
+%ifndef __TINY__
+        push cs
+        pop ds
+%endif
+        mov dx, FPC_INT00_HANDLER
+        mov ax, 2500h
+        int 21h
+
+        pop ds
+%ifdef __FAR_CODE__
+        retf
+%else
+        ret
+%endif
+
+
+        global FPC_RESTORE_INTERRUPT_HANDLERS
+FPC_RESTORE_INTERRUPT_HANDLERS:
+        push ds
+
+        mov ax, 2500h
+        lds dx, [__SaveInt00]
+        int 21h
+
+        pop ds
+%ifdef __FAR_CODE__
+        retf
+%else
+        ret
+%endif
+
+
         global FPC_MSDOS_CARRY
         global FPC_MSDOS_CARRY
 FPC_MSDOS_CARRY:
 FPC_MSDOS_CARRY:
         stc
         stc

+ 7 - 0
rtl/msdos/system.pp

@@ -63,6 +63,8 @@ var
 
 
   dos_psp:Word;public name 'dos_psp';
   dos_psp:Word;public name 'dos_psp';
 
 
+  SaveInt00: FarPointer;public name '__SaveInt00';
+
   AllFilesMask: string [3];
   AllFilesMask: string [3];
 {$ifndef RTLLITE}
 {$ifndef RTLLITE}
 { System info }
 { System info }
@@ -111,6 +113,9 @@ procedure MsDos(var Regs: Registers); external name 'FPC_MSDOS';
   support them }
   support them }
 procedure MsDos_Carry(var Regs: Registers); external name 'FPC_MSDOS_CARRY';
 procedure MsDos_Carry(var Regs: Registers); external name 'FPC_MSDOS_CARRY';
 
 
+procedure InstallInterruptHandlers; external name 'FPC_INSTALL_INTERRUPT_HANDLERS';
+procedure RestoreInterruptHandlers; external name 'FPC_RESTORE_INTERRUPT_HANDLERS';
+
 {$I system.inc}
 {$I system.inc}
 
 
 {$I tinyheap.inc}
 {$I tinyheap.inc}
@@ -264,6 +269,7 @@ procedure system_exit;
 var
 var
   h : byte;
   h : byte;
 begin
 begin
+  RestoreInterruptHandlers;
   for h:=0 to max_files-1 do
   for h:=0 to max_files-1 do
     if openfiles[h] then
     if openfiles[h] then
       begin
       begin
@@ -333,6 +339,7 @@ begin
   StackTop := __stktop;
   StackTop := __stktop;
   StackBottom := __stkbottom;
   StackBottom := __stkbottom;
   StackLength := __stktop - __stkbottom;
   StackLength := __stktop - __stkbottom;
+  InstallInterruptHandlers;
   if DetectFPU then
   if DetectFPU then
     SysInitFPU;
     SysInitFPU;
   { To be set if this is a GUI or console application }
   { To be set if this is a GUI or console application }