fpc/docs/go32ex/rmpm_int.pas
1998-09-07 20:53:46 +00:00

120 lines
3.3 KiB
ObjectPascal

{ example for :
interrupt redirection
software vs. hardware interrupts
set_pm_interrupt()
get_pm_interrupt()
get_cs()
tseginfo
trealregs
processor access
get_cs(), get_ds(), get_ss()
}
{ 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, { used for clreol(), gotoxy() }
go32;
{$ASMMODE DIRECT}
var r : trealregs;
axreg : Word; { temporary variable used for the protected mode int call }
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 CallOld
movw $0x3112, %ax
iret
CallOld:
ljmp %cs:OLDHANDLER
OLDHANDLER: .long 0
.word 0
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);
{ storing old handler address in interrupt handler }
asm
movl _OLDINT21H, %eax
movl %eax, OLDHANDLER
movw 4+_OLDINT21H, %ax
movw %ax, 4+OLDHANDLER
end;
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 ');
Writeln('calling interrupts...');
set_pm_interrupt($21, oldint21h);
end.