INT24.MOD 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. IMPLEMENTATION MODULE Int24 ;
  2. (*========================================================
  3. == TopSpeed Modula-2 V3 ==
  4. == demo program: ==
  5. == ==
  6. == Int24 handler ==
  7. == ==
  8. == Skeleton handler for "critical errors" ==
  9. == ==
  10. ========================================================*)
  11. (*# check(stack=>off,index=>off,range=>off,overflow=>off,nil_ptr=>off) *)
  12. (* Example of defining an interrupt handler in Modula-2 *)
  13. IMPORT SYSTEM,Lib,Str ;
  14. CONST
  15. ContinueProg = FALSE; (* Set this to TRUE if you want to continue
  16. after an abort (returning 255 to the
  17. calling program).
  18. If ContinueProg is set to FALSE then the
  19. program will terminate on 'abort' *)
  20. (*----------------------------------------------------------------------*)
  21. (* These are "safe" version of IO routines,
  22. i.e. they do not call any DOS function > 12
  23. Alternatively "Window" routines could be used.
  24. *)
  25. PROCEDURE WrStr(string: ARRAY OF CHAR);
  26. VAR R : SYSTEM.Registers;
  27. i : CARDINAL;
  28. BEGIN
  29. i := 0;
  30. WHILE (i<SIZE(string))AND(string[i]<>CHR(0)) DO
  31. R.DL := SHORTCARD(string[i]);
  32. R.AH := 6;
  33. Lib.Intr( R ,21H ); (* Don't use Lib.Dos as this will trigger
  34. re-entered check *)
  35. INC(i);
  36. END;
  37. END WrStr;
  38. PROCEDURE WrLn;
  39. TYPE
  40. a3 = ARRAY [0..1] OF CHAR;
  41. CONST
  42. crlf = a3(CHR(13),CHR(10));
  43. BEGIN
  44. WrStr( crlf );
  45. END WrLn;
  46. PROCEDURE RdKey(): CHAR;
  47. VAR R : SYSTEM.Registers;
  48. BEGIN
  49. R.AH := 7;
  50. Lib.Intr( R ,21H ); (* Don't use Lib.Dos as this will trigger
  51. re-entered check *)
  52. RETURN CHAR(R.AL);
  53. END RdKey;
  54. (*----------------------------------------------------------------------*)
  55. (* The pop stack inline code is required if the program should
  56. continue after an abort (returning 255 to the calling program).
  57. *)
  58. TYPE
  59. Code26 = ARRAY[0..25] OF SHORTCARD ;
  60. (*# save,
  61. call( reg_saved=>(dx,ax,bx,cx,si,di,es,ds,st1,st2),
  62. inline=>on )
  63. *)
  64. PROCEDURE PopStack()=Code26(
  65. 08BH,0E5H, (* mov sp,bp *)
  66. 083H,0C4H,01CH, (* add sp,1CH *)
  67. 058H, (* pop ax *)
  68. 05BH, (* pop bx *)
  69. 059H, (* pop cx *)
  70. 05AH, (* pop dx *)
  71. 05EH, (* pop si *)
  72. 05FH, (* pop di *)
  73. 058H, (* pop ax *)
  74. 01FH, (* pop ds *)
  75. 007H, (* pop es *)
  76. 08BH,0ECH, (* mov bp,sp *)
  77. 080H,04EH,004H,001H, (* or byte [bp][4],1 *)
  78. 08BH,0E8H, (* mov bp,ax *)
  79. 0B8H,0FFH,000H, (* mov ax,0FFH *)
  80. 0CFH); (* iret *)
  81. (*----------------------------------------------------------------------*)
  82. (* Actual Int24 Interrupt Handler
  83. *)
  84. (* pragmas for interrupt handler *)
  85. (*# save,
  86. call(interrupt => on,
  87. reg_param => (),
  88. same_ds => off
  89. )
  90. *)
  91. (* NB, The interrupt pragma sets up the registers as parameters to the
  92. procedure in the order defined below. This allows easy access to
  93. the entry registers
  94. *)
  95. PROCEDURE Irpt24 ( Flags : BITSET; (* Registers on entry *)
  96. CS,IP : CARDINAL;
  97. AX,CX : CARDINAL;
  98. DX,BX : CARDINAL;
  99. SP,BP : CARDINAL;
  100. SI,DI : CARDINAL;
  101. DS,ES : CARDINAL ) ;
  102. VAR
  103. s : ARRAY[0..40] OF CHAR ;
  104. k : CHAR ;
  105. saveipf : BOOLEAN ;
  106. P_AL : POINTER TO SHORTCARD;
  107. BEGIN
  108. (* N.B. Only DOS functions <= 12 may be called from a critical
  109. error handler
  110. *)
  111. CASE DI OF
  112. 0 : s := 'Disk write protected' |
  113. 2 : s := 'Drive not ready' |
  114. 9 : s := 'Printer out of paper' |
  115. ELSE
  116. s := 'Disk error' ;
  117. END ;
  118. Str.Append(s,'. Abort, Retry, Ignore?');
  119. WrStr(s) ; WrLn ;
  120. REPEAT
  121. k := CAP(RdKey()) ;
  122. UNTIL (k='R') OR (k='I') OR (k='A') ;
  123. P_AL := ADR(AX);
  124. IF k='I' THEN P_AL^ := 0 ; (* ignore *)
  125. ELSIF k='R' THEN P_AL^ := 1 ; (* retry *)
  126. ELSE (* abort *)
  127. IF ContinueProg THEN
  128. PopStack; (* Removes MSDOS call frame and Return 255 to caller *)
  129. (* Does not return here *)
  130. ELSE
  131. HALT ;
  132. END ;
  133. END ;
  134. END Irpt24;
  135. (*# restore *)
  136. VAR
  137. Int24Vec[0:24H*4] : FarADDRESS;
  138. VAR
  139. h : CARDINAL;
  140. BEGIN
  141. SYSTEM.DI ;
  142. (* Install interrupt 24 *)
  143. Int24Vec := FarADR(Irpt24) ;
  144. SYSTEM.EI ;
  145. END Int24.
  146.