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 103 104 105 106
| program dpmiwin; {from c't 1/1992 # 197}
uses
winprocs,
wintypes,
win31,
wincrt;
type
tDPMICallStruc = Record {for use by RMInterrupt}
EDI, ESI, EBP, Reserved,
EBX, EDX, ECX, EAX : longint;
Flags, ES, DS, FS,
GS, IP, CS, SP, SS : word;
end;
function RMInterrupt(IntNo, flags, copywords : byte;
var DPMICallStruc : tDPMICallStruc) : boolean;
begin
asm
push es {save es en di from protected mode on stack}
push di
mov bh, flags {if bit 0 is zero interrupt controller ...}
{... and A20-line will be reset. other bits must be zero}
mov bl, intno {put interrupt nummer to be executed in register bl}
mov cx, word ptr copywords {cx = number of words that are to be copied...}
{ from... prot. mode to real mode stack}
mov ax, 0300h {put DPMI simulate real mode interrupt nummer in register ax}
les di, dpmiCallStruc {16-bits pointer to record - 32 bits uses edi}
{les di, ...: load segment (2 bytes) dpmicallstruc in}
{ register di en offset (ook 2 bytes) }
{ in register es. in short load pointer to dpmicallstruc}
{ in registers di:es }
int 31h {excute interrupt nummer in bl in real-mode after filling }
{ cpu-registers with values from dpmicallstruc and return in}
{ protected mode with contents of cpu-registers at end of real-mode}
{ interrupt in dpmicallstruc. i.o.w. act as if dpmicallstruc }
{ are the cpu-registers at the end of excuting the real-mode int.}
jc @error
mov ax, 1 {function succesfull}
jmp @done
@error:
xor ax, ax {make ax=0, function not succesfull}
@done:
pop di {put es and di back}
pop es
end;
end;
var
selector : word;
segment : word;
selseg : longint;
dcs : tdpmicallstruc;
printstrg : pchar;
begin
fillchar(dcs, sizeof(dcs), 0); {zero dcs}
{------- verify presence of dpmitsr in memory}
dcs.eax := $00000000; {just for clarity that ax is called with function 0}
{ as contents is already zero because of use}
{ of function filchar() on previous line. }
rminterrupt($61, 0, 0, dcs);
if (dcs.eax and $ffff = $affe) then
writeln('DPMItsr in memory')
else
writeln('Something went wrong!');
{this part needs improvement. }
{if dpmitsr is not in memory then pc may crash,}
{ which is not strange as then an interrupt }
{ is called that most likely is 0000:0000 in }
{ memory. }
{this is to be substituted with a routine that first checks}
{ that pointer of int. 61 is not 0000:0000. }
{------- read string through pointer}
dcs.eax := $00000100; {call int. 61 (=dpmitsr) with ah = 1}
rminterrupt($61, 0, 0, dcs);
selector := allocselector(word(nil)); {make new selector and fill with values:}
setselectorbase(selector, longint(dcs.es) * 16);
{ base: es is put in by 'dpmitsr'}
setselectorlimit(selector, longint($ffff));
{ and limit: $ffff is maximum value. this}
{ does not give problems because we put a}
{ 'zero-terminated' string on the screen.}
printstrg := ptr(selector, word(dcs.edi)); {also di is put in by 'dpmitsr' }
writeln(printstrg);
freeselector(selector);
{------- read string by making a copy from real-mode memory to
Windows-memory in low 640k-area}
selseg := globaldosalloc(100); {allocate 100 bytes Windows-memory below 640k.}
{high word of longint 'selseg' is segment for }
{ use in real-mode and low word is selector }
{ for use in protected mode. }
if selseg <> 0 then
begin
selector := word(selseg and $ffff); {determine selector}
segment := word(selseg shr 16); {determine segment}
dcs.eax := $00000200; {call int. 61 (=dpmitsr) with ah = 2 }
dcs.es := segment; {use segment for int. 61 in real-mode}
dcs.edi := 0; {offset is 0 }
rminterrupt($61, 0, 0, dcs);
printstrg := ptr(selector, 0);
writeln(printstrg);
globaldosfree(selector);
end;
end. |
Partager