rmpm_int.pas 3.3 KB

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