rmpmint.pas 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. { This example shows the difference between protected and real mode
  2. interrupts; it redirects the protected mode handler to an own handler
  3. which returns an impossible function result and calls it afterwards.
  4. Then the real mode handler is called directly, to show the difference
  5. between the two.
  6. Used Interrupt:
  7. get DOS version Int 21h / function 30h
  8. Input: AH = $30
  9. AL = $1
  10. Return: AL = major version number
  11. AH = minor version number
  12. }
  13. uses
  14. crt,
  15. go32;
  16. var
  17. r : trealregs;
  18. { temporary variable used for the protected mode int call }
  19. axreg : Word;
  20. oldint21h : tseginfo;
  21. newint21h : tseginfo;
  22. { this is our int 21h protected mode interupt handler. It catches
  23. the function call to get the DOS version, all other int 21h calls
  24. are redirected to the old handler; it is written in assembly
  25. because the old handler can't be called with pascal }
  26. procedure int21h_handler; assembler;
  27. asm
  28. cmpw $0x3001, %ax
  29. jne .LCallOld
  30. movw $0x3112, %ax
  31. iret
  32. .LCallOld:
  33. ljmp %cs:oldint21h
  34. end;
  35. { a small helper procedure, which waits for a keypress }
  36. procedure resume;
  37. begin
  38. Writeln;
  39. Write('-- press any key to resume --'); readkey;
  40. gotoxy(1, wherey); clreol;
  41. end;
  42. begin
  43. { see the text messages for further detail }
  44. clrscr;
  45. Writeln('Executing real mode interrupt');
  46. resume;
  47. r.ah := $30; r.al := $01; realintr($21, r);
  48. Writeln('DOS v', r.al,'.',r.ah, ' detected');
  49. resume;
  50. Writeln('Executing protected mode interrupt without our own',
  51. ' handler');
  52. Writeln;
  53. asm
  54. movb $0x30, %ah
  55. movb $0x01, %al
  56. int $0x21
  57. movw %ax, axreg
  58. end;
  59. Writeln('DOS v', r.al,'.',r.ah, ' detected');
  60. resume;
  61. Writeln('As you can see the DPMI hosts default protected mode',
  62. 'handler');
  63. Writeln('simply redirects it to the real mode handler');
  64. resume;
  65. Writeln('Now exchanging the protected mode interrupt with our ',
  66. 'own handler');
  67. resume;
  68. newint21h.offset := @int21h_handler;
  69. newint21h.segment := get_cs;
  70. get_pm_interrupt($21, oldint21h);
  71. set_pm_interrupt($21, newint21h);
  72. Writeln('Executing real mode interrupt again');
  73. resume;
  74. r.ah := $30; r.al := $01; realintr($21, r);
  75. Writeln('DOS v', r.al,'.',r.ah, ' detected');
  76. Writeln;
  77. Writeln('See, it didn''t change in any way.');
  78. resume;
  79. Writeln('Now calling protected mode interrupt');
  80. resume;
  81. asm
  82. movb $0x30, %ah
  83. movb $0x01, %al
  84. int $0x21
  85. movw %ax, axreg
  86. end;
  87. Writeln('DOS v', lo(axreg),'.',hi(axreg), ' detected');
  88. Writeln;
  89. Writeln('Now you can see that there''s a distinction between ',
  90. 'the two ways of calling interrupts...');
  91. set_pm_interrupt($21, oldint21h);
  92. end.