File: rmpmint.pas

package info (click to toggle)
fpc 1.9.4-5
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 63,532 kB
  • ctags: 93,677
  • sloc: pascal: 675,850; makefile: 219,089; xml: 9,242; perl: 7,703; yacc: 3,074; ansic: 2,275; lex: 711; sh: 406; asm: 71; csh: 34; sed: 33; cpp: 26; tcl: 7
file content (102 lines) | stat: -rw-r--r-- 2,578 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
{ This example shows the difference between protected and real mode
interrupts; it redirects the protected mode handler to an own handler
which returns an impossible function result and calls it afterwards.
Then the real mode handler is called directly, to show the difference
between the two.

Used Interrupt:
get DOS version Int 21h / function 30h
     Input: AH = $30
            AL = $1
     Return: AL = major version number
             AH = minor version number
}

uses
	crt,
	go32;

var
	r : trealregs;
	{ temporary variable used for the protected mode int call }
	axreg : Word;

	oldint21h : tseginfo;
	newint21h : tseginfo;

{ this is our int 21h protected mode interupt handler. It catches
the function call to get the DOS version, all other int 21h calls
are redirected to the old handler; it is written in assembly
because the old handler can't be called with pascal }
procedure int21h_handler; assembler;
asm
	cmpw $0x3001, %ax
	jne .LCallOld
	movw $0x3112, %ax
	iret

.LCallOld:
	ljmp %cs:oldint21h
end;

{ a small helper procedure, which waits for a keypress }
procedure resume;
begin
	Writeln;
	Write('-- press any key to resume --'); readkey;
	gotoxy(1, wherey); clreol;
end;

begin
	{ see the text messages for further detail }
	clrscr;
	Writeln('Executing real mode interrupt');
	resume;
	r.ah := $30; r.al := $01;  realintr($21, r);
	Writeln('DOS v', r.al,'.',r.ah, ' detected');
	resume;
	Writeln('Executing protected mode interrupt without our own',
		' handler');
	Writeln;
	asm
		movb $0x30, %ah
		movb $0x01, %al
		int $0x21
		movw %ax, axreg
	end;
	Writeln('DOS v', r.al,'.',r.ah, ' detected');
	resume;
	Writeln('As you can see the DPMI hosts default protected mode',
		'handler');
	Writeln('simply redirects it to the real mode handler');
	resume;
	Writeln('Now exchanging the protected mode interrupt with our ',
		'own handler');
	resume;

	newint21h.offset := @int21h_handler;
	newint21h.segment := get_cs;
	get_pm_interrupt($21, oldint21h);
	set_pm_interrupt($21, newint21h);

	Writeln('Executing real mode interrupt again');
	resume;
	r.ah := $30; r.al := $01; realintr($21, r);
	Writeln('DOS v', r.al,'.',r.ah, ' detected');
	Writeln;
	Writeln('See, it didn''t change in any way.');
	resume;
	Writeln('Now calling protected mode interrupt');
	resume;
	asm
		movb $0x30, %ah
		movb $0x01, %al
		int $0x21
		movw %ax, axreg
	end;
	Writeln('DOS v', lo(axreg),'.',hi(axreg), ' detected');
	Writeln;
	Writeln('Now you can see that there''s a distinction between ',
		'the two ways of calling interrupts...');
	set_pm_interrupt($21, oldint21h);
end.