home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / turbo4 / ems.pas < prev    next >
Pascal/Delphi Source File  |  1987-12-08  |  12KB  |  341 lines

  1. program Ems_Test;
  2. { ***************************************************************
  3.   * Dieses Programm demonstriert die Zugriffsmöglichkeiten      *
  4.   * auf Speichererweiterungen nach dem LIM-EMS-Standard         *
  5.   * ("Lotus Intel Microsoft Expanded Memory"). Es verwendet     *
  6.   * keine der 'höheren' EMS-Funktionen und ist deshalb auch auf *
  7.   * Systemen lauffähig, die mit EMS-Versionen vor 4.0 arbeiten. *
  8.   ***************************************************************
  9.  
  10.   Geschrieben von:
  11.     Peter Immarco
  12.     Thought Dynamics
  13.     Manhattan Beach, CA
  14.     Compuserve ID# 73770,123
  15.      *** Public Domain ***
  16.  
  17.   Die Wiedergabe erfolgt mit freundlicher Genehmigung des Autors.
  18. }
  19.  
  20. { Dieses Programm führt die folgenden Schritte aus:
  21.   * Prüfung, ob der LIM Expanded Memory Manager (EMM) im Hauptspeicher
  22.     installiert wurde
  23.   * Ausgabe der Versionsnummer des EMM
  24.   * Bestimmung, ob genügend Speicherblocks (mit jeweils 16 KByte) EMS
  25.     zur freien Verfügung stehen, Ausgabe der Anzahl freier/belegter Blocks
  26.   * Anforderung einer bestimmten Anzahl von Speicherblocks
  27.   * Zuordnung einer logischen Seite zu einem der angeforderten physikalischen
  28.     Speicherblocks, Ausgabe der entsprechenden EMS-Basisadresse
  29.   * Ausführung eines einfachen Lese- und Schreibtests in dieser Seite
  30.   * Rückgabe des belegten Speicherplatzes an den EMM und Ende.
  31.  
  32.  
  33.   Alle Aufrufe liefern das Ergebnis bzw. den Statuscode der aufgerufenen
  34.   EMM-Funktion als Integerwert zurück. Für Statuscodes <> 0 (d.h. Fehler)
  35.   führt das Programm eine einfache Fehlerbehandlung aus und bricht dann ab.
  36. }
  37.  
  38. uses Crt, Dos;
  39.  
  40. type
  41.   ST3  = string[3];
  42.   ST80 = string[80];
  43.   ST5 = string[5];
  44.  
  45. const
  46.   EMM_INT                   = $67;
  47.   DOS_Int                   = $21;
  48.   GET_PAGE_FRAME            = $41;
  49.   GET_UNALLOCATED_PAGE_COUNT= $42;
  50.   ALLOCATE_PAGES            = $43;
  51.   MAP_PAGES                 = $44;
  52.   DEALLOCATE_PAGES          = $45;
  53.   GET_VERSION               = $46;
  54.  
  55.   STATUS_OK = 0;
  56.  
  57.   { Wir gehen davon aus, daß wir nur eine einzige EMS-Seite für unser
  58.     Programm benötigen }
  59.   APPLICATION_PAGE_COUNT    = 1;
  60.  
  61. var
  62.   Regs: Registers;
  63.   Emm_Handle,
  64.   Page_Frame_Base_Address,
  65.   Pages_Needed,
  66.   Physical_Page,
  67.   Logical_Page,
  68.   Offset,
  69.   Error_Code,
  70.   Pages_EMS_Avail,
  71.   Total_EMS_Pages,
  72.   Available_EMS_Pages: Word;
  73.   Version_Number,
  74.   Pages_Number_String: ST3;
  75.   Verify: Boolean;
  76.  
  77. { * --------------------------------------------------------- * }
  78. function Hex_String(Number: Word): ST5;
  79. { Konvertiert den übergebenen Wert (Typ Word) in einen String mit vier
  80.   Hexadezimalzeichen (und nötigenfalls führenden Nullen) }
  81.   function Hex_Char(Number: Word): Char;
  82.     begin
  83.       if Number<10 then Hex_Char:=Char(Number+48)
  84.       else Hex_Char:=Char(Number+55);
  85.     end; { Hex_Char }
  86.  
  87.   var
  88.     S: ST5;
  89.   begin
  90.     S:='';
  91.     S:=Hex_Char( (Number shr 1) div 2048);
  92.     Number:=( ((Number shr 1) mod 2048) shl 1)+ (Number and 1) ;
  93.     S:=S+Hex_Char(Number div 256);
  94.     Number:=Number mod 256;
  95.     S:=S+Hex_Char(Number div 16);
  96.     Number:=Number mod 16;
  97.     S:=S+Hex_Char(Number);
  98.     Hex_String:=S+'h';
  99.   end; { Hex_String }
  100.  
  101.  
  102. function Emm_Installed: Boolean;
  103. { Prüft, ob der Expanded Memory Manager (EMM) installiert (d.h in den
  104.   Hauptspeicher geladen) ist. Falls ja, sollte sich der String 'EMMXXXX0'
  105.   auf der Offset-Adresse $0010 des Segments befinden, auf den der EMM-
  106.   Interrupt-Vektor ($67) zeigt.
  107.   Liefert TRUE, wenn EMM installiert, ansonsten FALSE }
  108. var
  109.   Emm_Device_Name       : string[8];
  110.   Int_67_Device_Name    : string[8];
  111.   Position              : Word;
  112.   Regs                  : registers;
  113.  
  114.   begin
  115.     Int_67_Device_Name:='';
  116.     Emm_Device_Name   :='EMMXXXX0';
  117.     with Regs do
  118.     begin
  119.       { Ermittlung des Segments, auf den der Interrupt-Vektor $67 zeigt
  120.         über die DOS-Funktion $35 ("Get Interrupt Vector") }
  121.       AH:=$35; AL:=EMM_INT;
  122.       Intr(DOS_int,Regs);   { liefert das Segment im ES-Register zurück }
  123.       for Position:=0 to 7 do
  124.         Int_67_Device_Name:=   { Auslesen von 8 Bytes ab dem Offset $0A }
  125.           Int_67_Device_Name + Chr(Mem[ES:$0A+Position]);
  126.       Emm_Installed := (Int_67_Device_Name = Emm_Device_Name);
  127.     end; { with Regs do }
  128.   end;  { Emm_Installed }
  129.  
  130.  
  131. function EMS_Pages_Avail (var Total_EMS_Pages,Pages_Avail: Word): Word;
  132. { Ermittelt die Gesamtzahl der EMS-Seiten und die Anzahl der für uns
  133.   verfügbaren Seiten }
  134. var
  135.   Regs: Registers;
  136. begin
  137.     with Regs do
  138.     begin
  139.       AH:=Get_Unallocated_Page_Count;   { EMM-Funktion: freie Seiten ermitteln }
  140.       Intr(EMM_INT,Regs);   { EMM-Aufruf }
  141.       Pages_Avail:=BX;      {    liefert freie Seiten in BX zurück }
  142.       Total_EMS_Pages:=DX;  {    und Gesamtzahl der Seiten in DX }
  143.       EMS_Pages_Avail:=AH   {    sowie einen eventuellen Fehlercode in AH }
  144.     end;  { with Regs }
  145.   end;
  146.  
  147.  
  148. function Alloc_EMS_Pages (Pages_Needed: Word; var Handle: Word): Word;
  149. { Fordert eine oder mehrere EMS-Seiten über einen EMM-Aufruf an }
  150. var
  151.   Regs: Registers;
  152. begin
  153.     with Regs do
  154.     begin
  155.       AH:= Allocate_Pages;     { EMM-Funktion: Speicherseiten belegen }
  156.       BX:=Pages_Needed;        { BX: Anzahl der gewünschten Seiten }
  157.       intr(EMM_INT,Regs);      { EMM-Aufruf }
  158.       Handle:=DX;              {    liefert einen Handle in DX zurück }
  159.       Alloc_EMS_Pages:=AH;  { und einen evtl. Fehlercode in AH }
  160.     end;  { with Regs }
  161.   end;
  162.  
  163. function Map_EM_Pages (Handle,Logical_Page,Physical_Page: Word): Word;
  164. { Ordnet einer physikalischen EMS-Seite (die via Alloc_EMS_Pages belegt
  165.   wurde) eine logische Speicherseite zu }
  166. var
  167.    Regs: Registers;
  168. begin
  169.   with Regs do
  170.     begin
  171.       AH:=Map_Pages;     { EMM-Funktion: physikalisch/logische Zuordnung }
  172.       AL:=Physical_Page;    {     AL: physikalische Nummer }
  173.       BX:=Logical_Page;     {     BX: logische Seitennummer }
  174.       DX:=Handle;           {     DX: Handle }
  175.       Intr(EMM_INT,Regs);   { EMM-Aufruf }
  176.       Map_EM_Pages:=AH;     {  liefert einen eventueller Fehlercode in AH }
  177.     end; { with Regs }
  178.   end;
  179.  
  180.  
  181. function Get_Page_Frame_Base_Address (var Page_Frame_Address: Word): Word;
  182. { Liefert die physikalische Basisadresse (= Segment) zurück }
  183. var
  184.   Regs: Registers;
  185. begin
  186.     with Regs do
  187.     begin
  188.       AH:=Get_Page_Frame;        { EMM-Funktion: Basisadresse ermitteln }
  189.       Intr(EMM_INT,Regs);        { EMM-Aufruf }
  190.       Page_Frame_Address:=BX;    {   liefert die Basisadresse in BX zurück }
  191.       Get_Page_Frame_Base_Address:=AH;  { und einen evtl. Fehlercode in AH }
  192.      end; { with Regs }
  193.   end;
  194.  
  195. function Deallocate_EM_Pages (Handle: Word): Word;
  196. { Gibt die zuvor belegten EMS-Seiten wieder frei }
  197. var
  198.   Regs: Registers;
  199. begin
  200.    with Regs do
  201.     begin
  202.       AH:=DEALLOCATE_PAGES;     { EMM-Funktion: Freigabe }
  203.       DX:=Emm_Handle;           {   DX: Handle für die frezugebenden Seiten }
  204.       Intr(EMM_INT,Regs);       { EMM-Aufruf }
  205.       Deallocate_EM_Pages:=AH;    { evtl. Fehlercode in AH }
  206.     end; { with Regs }
  207.   end;
  208.  
  209. function Get_Version_Number(var Version_String: ST3): Word;
  210. { Liefert die EMM-Versionsnummer als String (mit 3 Zeichen) zurück }
  211. var
  212.  Regs: Registers;
  213.  Word_Part,Fractional_Part: Char;
  214. begin
  215.     with Regs do
  216.     begin
  217.       AH:=GET_VERSION;        { EMM-Funktion: Versionsnummer }
  218.       Intr(EMM_INT,Regs);     { EMM-Aufruf }
  219.       if AH=STATUS_OK then    { wenn kein Fehler: }
  220.       begin
  221.         { Bits 7..4 von AL: Haupt-Versionsnummer, Bits 3..0: Neben-Version }
  222.         Word_Part   := Char( AL shr 4 + 48);  { Konvertierung in ein Zeichen }
  223.         Fractional_Part:= Char( AL and $F +48); { dito für Neben-Versionsnummer }
  224.         Version_String:= Word_Part+'.'+Fractional_Part; { z.B. '3.1' }
  225.       end;
  226.       Get_Version_Number:=AH;  { eventueller Fehlercode... }
  227.     end; { with Regs }
  228.   end;
  229.  
  230. procedure Error(Error_Message: ST80; Error_Number: Word);
  231. { Gibt die als Error_Message übergebene Meldung und die als Error_Number
  232.   übergebene Zahl (hexadezimal) aus und bricht das Programm mit einem
  233.   Exit-Code von 1 ab. }
  234. begin
  235.     Writeln(Error_Message);
  236.     Writeln('  Fehlernummer: ',Hex_String(Error_Number) );
  237.     Writeln('EMS-Testprogramm abgebrochen.');
  238.     Halt(1);
  239.   end;
  240.  
  241. { *************************************************************** }
  242. { *************************************************************** }
  243. begin  { Hauptprogramm }
  244.   ClrScr;
  245.   Window(5,2,77,22);
  246.  
  247.   if not (Emm_Installed) then  { EMM installiert? }
  248.   begin
  249.     Writeln('Der LIM Expanded Memory Manager ist nicht installiert.');
  250.     Halt(1);  { Abbruch mit Exitcode 1 }
  251.   end;
  252.  
  253.   { Ermittlung der EMM-Versionsnummer und Ausgabe }
  254.   Error_Code:= Get_Version_Number(Version_Number);
  255.   if Error_Code<>STATUS_OK then
  256.      Error('Fehler bei der Ermittlung der EMM-Versionsnummer.', Error_code)
  257.    else Writeln('EMM-Versionsnmummer: ', Version_Number);
  258.   Writeln;
  259.  
  260.   { Ermittlung der Gesamtzahl EMS-Seiten und der Anzahl freier Seiten }
  261.   Pages_Needed:=APPLICATION_PAGE_COUNT;
  262.   Error_Code:= EMS_Pages_Avail(Total_EMS_Pages,Available_EMS_Pages);
  263.   if Error_Code<>STATUS_OK then
  264.     Error('Fehler beim Versuch, die Anzahl freier EMS-Seiten zu ermitteln.',
  265.             Error_Code);
  266.  
  267.   Writeln('Das System verfügt insgesamt über ',Total_EMS_Pages,
  268.           ' EMS-Seiten.');
  269.   Writeln('  ',Available_EMS_Pages,
  270.           ' davon sind für unser Programm verfügbar.');
  271.   Writeln;
  272.  
  273.   if Pages_Needed>Available_EMS_Pages then  { nicht genug freie Seiten? }
  274.   begin
  275.     Str(Pages_Needed,Pages_Number_String);
  276.     Error('Unser Programm erwartet allerdings '+Pages_Number_String+
  277.           ' EMS-Seiten. ', Error_Code);
  278.   end;
  279.  
  280.   { Tatsächliche Belegung der EMS-Speicherseiten }
  281.   Error_Code:= Alloc_EMS_Pages(Pages_Needed,Emm_Handle);
  282.   Str(Pages_Needed,Pages_Number_String);
  283.   if Error_Code<>STATUS_OK then
  284.     Error('Fehler beim Versuch, '+Pages_Number_String+
  285.           ' EMS-Seiten zu belegen.',Error_Code);
  286.   Writeln(APPLICATION_PAGE_COUNT,
  287.           ' EMS-Seite(n) für unser Programm belegt!');
  288.   Writeln;
  289.  
  290.   { Zuordnung der logischen Seiten auf physikalische Seiten (für unser
  291.     Testprogramm läuft das auf eine einzige Zuordnung hinaus) }
  292.   Logical_Page :=0; Physical_Page:=0;
  293.   Error_Code:= Map_EM_Pages(Emm_Handle,Logical_Page,Physical_Page);
  294.   if Error_Code<>STATUS_OK then
  295.     Error('Fehler bei der logisch/physikalischen Zuordnung.', Error_Code);
  296.  
  297.   Writeln('Logische Seite ',Logical_Page, ' wurde der physikalischen Seite ',
  298.           Physical_Page, 'zugeordnet.');
  299.   Writeln;
  300.  
  301.   { Ermittlung der Basisadresse }
  302.   Error_Code:= Get_Page_Frame_Base_Address(Page_Frame_Base_Address);
  303.   if Error_Code<>STATUS_OK then
  304.     Error('Fehler bei der Ermittlung der Basisadresse.', Error_Code);
  305.   Writeln('Die Basisadresse der belegten Speicherseite(n) ist: ' +
  306.           Hex_String(Page_Frame_Base_Address) );
  307.   Writeln;
  308.  
  309.   { Schreiben eines Bitmusters in die belegte EMS-Seite }
  310.   for Offset:=0 to 16382 do
  311.     Mem[Page_Frame_Base_Address:Offset]:=Offset mod 256;
  312.  
  313.   { und Prüfung }
  314.   Writeln('Prüfung der EMS-Seite...');
  315.  
  316.   Offset:=1;
  317.   Verify:=True;
  318.   while (Offset<=16382) and (Verify=True) do
  319.   begin
  320.     if Mem[Page_Frame_Base_Address:Offset]<>Offset mod 256 then
  321.       Verify:=False;
  322.     Offset:=Succ(Offset);
  323.   end;  { while }
  324.  
  325.   if not Verify then
  326.   begin
  327.     Writeln('Fehler: Speicherung inkonsistent!!');
  328.     Halt(1);
  329.    end;
  330.   Writeln('EMS-Speichertest fehlerfrei beendet.');
  331.   Writeln;
  332.  
  333.   { Rückgabe der belegten Speicherseiten }
  334.   Error_Code:=Deallocate_EM_Pages(Emm_Handle);
  335.   if Error_Code<>STATUS_OK then
  336.     Error('Fehler bei der Rückgabe belegter EMS-Seiten.', Error_Code);
  337.   Writeln(APPLICATION_PAGE_COUNT, ' EMS-Seite(n) wieder freigegeben.');
  338.   Writeln;
  339.   Writeln('EMS-Testprogramm normal beendet.');
  340. end.
  341.