home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
turbo4
/
ems.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1987-12-08
|
12KB
|
341 lines
program Ems_Test;
{ ***************************************************************
* Dieses Programm demonstriert die Zugriffsmöglichkeiten *
* auf Speichererweiterungen nach dem LIM-EMS-Standard *
* ("Lotus Intel Microsoft Expanded Memory"). Es verwendet *
* keine der 'höheren' EMS-Funktionen und ist deshalb auch auf *
* Systemen lauffähig, die mit EMS-Versionen vor 4.0 arbeiten. *
***************************************************************
Geschrieben von:
Peter Immarco
Thought Dynamics
Manhattan Beach, CA
Compuserve ID# 73770,123
*** Public Domain ***
Die Wiedergabe erfolgt mit freundlicher Genehmigung des Autors.
}
{ Dieses Programm führt die folgenden Schritte aus:
* Prüfung, ob der LIM Expanded Memory Manager (EMM) im Hauptspeicher
installiert wurde
* Ausgabe der Versionsnummer des EMM
* Bestimmung, ob genügend Speicherblocks (mit jeweils 16 KByte) EMS
zur freien Verfügung stehen, Ausgabe der Anzahl freier/belegter Blocks
* Anforderung einer bestimmten Anzahl von Speicherblocks
* Zuordnung einer logischen Seite zu einem der angeforderten physikalischen
Speicherblocks, Ausgabe der entsprechenden EMS-Basisadresse
* Ausführung eines einfachen Lese- und Schreibtests in dieser Seite
* Rückgabe des belegten Speicherplatzes an den EMM und Ende.
Alle Aufrufe liefern das Ergebnis bzw. den Statuscode der aufgerufenen
EMM-Funktion als Integerwert zurück. Für Statuscodes <> 0 (d.h. Fehler)
führt das Programm eine einfache Fehlerbehandlung aus und bricht dann ab.
}
uses Crt, Dos;
type
ST3 = string[3];
ST80 = string[80];
ST5 = string[5];
const
EMM_INT = $67;
DOS_Int = $21;
GET_PAGE_FRAME = $41;
GET_UNALLOCATED_PAGE_COUNT= $42;
ALLOCATE_PAGES = $43;
MAP_PAGES = $44;
DEALLOCATE_PAGES = $45;
GET_VERSION = $46;
STATUS_OK = 0;
{ Wir gehen davon aus, daß wir nur eine einzige EMS-Seite für unser
Programm benötigen }
APPLICATION_PAGE_COUNT = 1;
var
Regs: Registers;
Emm_Handle,
Page_Frame_Base_Address,
Pages_Needed,
Physical_Page,
Logical_Page,
Offset,
Error_Code,
Pages_EMS_Avail,
Total_EMS_Pages,
Available_EMS_Pages: Word;
Version_Number,
Pages_Number_String: ST3;
Verify: Boolean;
{ * --------------------------------------------------------- * }
function Hex_String(Number: Word): ST5;
{ Konvertiert den übergebenen Wert (Typ Word) in einen String mit vier
Hexadezimalzeichen (und nötigenfalls führenden Nullen) }
function Hex_Char(Number: Word): Char;
begin
if Number<10 then Hex_Char:=Char(Number+48)
else Hex_Char:=Char(Number+55);
end; { Hex_Char }
var
S: ST5;
begin
S:='';
S:=Hex_Char( (Number shr 1) div 2048);
Number:=( ((Number shr 1) mod 2048) shl 1)+ (Number and 1) ;
S:=S+Hex_Char(Number div 256);
Number:=Number mod 256;
S:=S+Hex_Char(Number div 16);
Number:=Number mod 16;
S:=S+Hex_Char(Number);
Hex_String:=S+'h';
end; { Hex_String }
function Emm_Installed: Boolean;
{ Prüft, ob der Expanded Memory Manager (EMM) installiert (d.h in den
Hauptspeicher geladen) ist. Falls ja, sollte sich der String 'EMMXXXX0'
auf der Offset-Adresse $0010 des Segments befinden, auf den der EMM-
Interrupt-Vektor ($67) zeigt.
Liefert TRUE, wenn EMM installiert, ansonsten FALSE }
var
Emm_Device_Name : string[8];
Int_67_Device_Name : string[8];
Position : Word;
Regs : registers;
begin
Int_67_Device_Name:='';
Emm_Device_Name :='EMMXXXX0';
with Regs do
begin
{ Ermittlung des Segments, auf den der Interrupt-Vektor $67 zeigt
über die DOS-Funktion $35 ("Get Interrupt Vector") }
AH:=$35; AL:=EMM_INT;
Intr(DOS_int,Regs); { liefert das Segment im ES-Register zurück }
for Position:=0 to 7 do
Int_67_Device_Name:= { Auslesen von 8 Bytes ab dem Offset $0A }
Int_67_Device_Name + Chr(Mem[ES:$0A+Position]);
Emm_Installed := (Int_67_Device_Name = Emm_Device_Name);
end; { with Regs do }
end; { Emm_Installed }
function EMS_Pages_Avail (var Total_EMS_Pages,Pages_Avail: Word): Word;
{ Ermittelt die Gesamtzahl der EMS-Seiten und die Anzahl der für uns
verfügbaren Seiten }
var
Regs: Registers;
begin
with Regs do
begin
AH:=Get_Unallocated_Page_Count; { EMM-Funktion: freie Seiten ermitteln }
Intr(EMM_INT,Regs); { EMM-Aufruf }
Pages_Avail:=BX; { liefert freie Seiten in BX zurück }
Total_EMS_Pages:=DX; { und Gesamtzahl der Seiten in DX }
EMS_Pages_Avail:=AH { sowie einen eventuellen Fehlercode in AH }
end; { with Regs }
end;
function Alloc_EMS_Pages (Pages_Needed: Word; var Handle: Word): Word;
{ Fordert eine oder mehrere EMS-Seiten über einen EMM-Aufruf an }
var
Regs: Registers;
begin
with Regs do
begin
AH:= Allocate_Pages; { EMM-Funktion: Speicherseiten belegen }
BX:=Pages_Needed; { BX: Anzahl der gewünschten Seiten }
intr(EMM_INT,Regs); { EMM-Aufruf }
Handle:=DX; { liefert einen Handle in DX zurück }
Alloc_EMS_Pages:=AH; { und einen evtl. Fehlercode in AH }
end; { with Regs }
end;
function Map_EM_Pages (Handle,Logical_Page,Physical_Page: Word): Word;
{ Ordnet einer physikalischen EMS-Seite (die via Alloc_EMS_Pages belegt
wurde) eine logische Speicherseite zu }
var
Regs: Registers;
begin
with Regs do
begin
AH:=Map_Pages; { EMM-Funktion: physikalisch/logische Zuordnung }
AL:=Physical_Page; { AL: physikalische Nummer }
BX:=Logical_Page; { BX: logische Seitennummer }
DX:=Handle; { DX: Handle }
Intr(EMM_INT,Regs); { EMM-Aufruf }
Map_EM_Pages:=AH; { liefert einen eventueller Fehlercode in AH }
end; { with Regs }
end;
function Get_Page_Frame_Base_Address (var Page_Frame_Address: Word): Word;
{ Liefert die physikalische Basisadresse (= Segment) zurück }
var
Regs: Registers;
begin
with Regs do
begin
AH:=Get_Page_Frame; { EMM-Funktion: Basisadresse ermitteln }
Intr(EMM_INT,Regs); { EMM-Aufruf }
Page_Frame_Address:=BX; { liefert die Basisadresse in BX zurück }
Get_Page_Frame_Base_Address:=AH; { und einen evtl. Fehlercode in AH }
end; { with Regs }
end;
function Deallocate_EM_Pages (Handle: Word): Word;
{ Gibt die zuvor belegten EMS-Seiten wieder frei }
var
Regs: Registers;
begin
with Regs do
begin
AH:=DEALLOCATE_PAGES; { EMM-Funktion: Freigabe }
DX:=Emm_Handle; { DX: Handle für die frezugebenden Seiten }
Intr(EMM_INT,Regs); { EMM-Aufruf }
Deallocate_EM_Pages:=AH; { evtl. Fehlercode in AH }
end; { with Regs }
end;
function Get_Version_Number(var Version_String: ST3): Word;
{ Liefert die EMM-Versionsnummer als String (mit 3 Zeichen) zurück }
var
Regs: Registers;
Word_Part,Fractional_Part: Char;
begin
with Regs do
begin
AH:=GET_VERSION; { EMM-Funktion: Versionsnummer }
Intr(EMM_INT,Regs); { EMM-Aufruf }
if AH=STATUS_OK then { wenn kein Fehler: }
begin
{ Bits 7..4 von AL: Haupt-Versionsnummer, Bits 3..0: Neben-Version }
Word_Part := Char( AL shr 4 + 48); { Konvertierung in ein Zeichen }
Fractional_Part:= Char( AL and $F +48); { dito für Neben-Versionsnummer }
Version_String:= Word_Part+'.'+Fractional_Part; { z.B. '3.1' }
end;
Get_Version_Number:=AH; { eventueller Fehlercode... }
end; { with Regs }
end;
procedure Error(Error_Message: ST80; Error_Number: Word);
{ Gibt die als Error_Message übergebene Meldung und die als Error_Number
übergebene Zahl (hexadezimal) aus und bricht das Programm mit einem
Exit-Code von 1 ab. }
begin
Writeln(Error_Message);
Writeln(' Fehlernummer: ',Hex_String(Error_Number) );
Writeln('EMS-Testprogramm abgebrochen.');
Halt(1);
end;
{ *************************************************************** }
{ *************************************************************** }
begin { Hauptprogramm }
ClrScr;
Window(5,2,77,22);
if not (Emm_Installed) then { EMM installiert? }
begin
Writeln('Der LIM Expanded Memory Manager ist nicht installiert.');
Halt(1); { Abbruch mit Exitcode 1 }
end;
{ Ermittlung der EMM-Versionsnummer und Ausgabe }
Error_Code:= Get_Version_Number(Version_Number);
if Error_Code<>STATUS_OK then
Error('Fehler bei der Ermittlung der EMM-Versionsnummer.', Error_code)
else Writeln('EMM-Versionsnmummer: ', Version_Number);
Writeln;
{ Ermittlung der Gesamtzahl EMS-Seiten und der Anzahl freier Seiten }
Pages_Needed:=APPLICATION_PAGE_COUNT;
Error_Code:= EMS_Pages_Avail(Total_EMS_Pages,Available_EMS_Pages);
if Error_Code<>STATUS_OK then
Error('Fehler beim Versuch, die Anzahl freier EMS-Seiten zu ermitteln.',
Error_Code);
Writeln('Das System verfügt insgesamt über ',Total_EMS_Pages,
' EMS-Seiten.');
Writeln(' ',Available_EMS_Pages,
' davon sind für unser Programm verfügbar.');
Writeln;
if Pages_Needed>Available_EMS_Pages then { nicht genug freie Seiten? }
begin
Str(Pages_Needed,Pages_Number_String);
Error('Unser Programm erwartet allerdings '+Pages_Number_String+
' EMS-Seiten. ', Error_Code);
end;
{ Tatsächliche Belegung der EMS-Speicherseiten }
Error_Code:= Alloc_EMS_Pages(Pages_Needed,Emm_Handle);
Str(Pages_Needed,Pages_Number_String);
if Error_Code<>STATUS_OK then
Error('Fehler beim Versuch, '+Pages_Number_String+
' EMS-Seiten zu belegen.',Error_Code);
Writeln(APPLICATION_PAGE_COUNT,
' EMS-Seite(n) für unser Programm belegt!');
Writeln;
{ Zuordnung der logischen Seiten auf physikalische Seiten (für unser
Testprogramm läuft das auf eine einzige Zuordnung hinaus) }
Logical_Page :=0; Physical_Page:=0;
Error_Code:= Map_EM_Pages(Emm_Handle,Logical_Page,Physical_Page);
if Error_Code<>STATUS_OK then
Error('Fehler bei der logisch/physikalischen Zuordnung.', Error_Code);
Writeln('Logische Seite ',Logical_Page, ' wurde der physikalischen Seite ',
Physical_Page, 'zugeordnet.');
Writeln;
{ Ermittlung der Basisadresse }
Error_Code:= Get_Page_Frame_Base_Address(Page_Frame_Base_Address);
if Error_Code<>STATUS_OK then
Error('Fehler bei der Ermittlung der Basisadresse.', Error_Code);
Writeln('Die Basisadresse der belegten Speicherseite(n) ist: ' +
Hex_String(Page_Frame_Base_Address) );
Writeln;
{ Schreiben eines Bitmusters in die belegte EMS-Seite }
for Offset:=0 to 16382 do
Mem[Page_Frame_Base_Address:Offset]:=Offset mod 256;
{ und Prüfung }
Writeln('Prüfung der EMS-Seite...');
Offset:=1;
Verify:=True;
while (Offset<=16382) and (Verify=True) do
begin
if Mem[Page_Frame_Base_Address:Offset]<>Offset mod 256 then
Verify:=False;
Offset:=Succ(Offset);
end; { while }
if not Verify then
begin
Writeln('Fehler: Speicherung inkonsistent!!');
Halt(1);
end;
Writeln('EMS-Speichertest fehlerfrei beendet.');
Writeln;
{ Rückgabe der belegten Speicherseiten }
Error_Code:=Deallocate_EM_Pages(Emm_Handle);
if Error_Code<>STATUS_OK then
Error('Fehler bei der Rückgabe belegter EMS-Seiten.', Error_Code);
Writeln(APPLICATION_PAGE_COUNT, ' EMS-Seite(n) wieder freigegeben.');
Writeln;
Writeln('EMS-Testprogramm normal beendet.');
end.