home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
doc
/
ems
/
demos
/
pasexamp
/
ems.pas
< prev
Wrap
Pascal/Delphi Source File
|
1988-04-22
|
23KB
|
527 lines
program EMM_example;
{----------------------------------------------------------------}
{ This program shows you how to use the basic functions of }
{ the LIM Expanded Memory Specification with Turbo Pascal. }
{ The program does the following: }
{ }
{ 1. Makes sure the LIM Expanded Memory Manager (EMM) has }
{ been installed. }
{ 2. Displays the version number of the EMM. }
{ 3. Determines if there are enough pages (16k blocks) of }
{ memory for our test program's usage. It then displays }
{ the total number of EMM pages present in the system, }
{ and how many are available for our use. }
{ 4. Requests the desired number of pages from the EMM. }
{ 5. Maps a logical page into one of the physical pages. }
{ 6. Displays the base address of our EMM memory page frame }
{ Performs a simple read/write test on the EMM memory. }
{ 7. Returns the EMM memory given to us back to the EMM. }
{ 8. Exits }
{ }
{ All the calls are structured to return the result or error }
{ code of the Expanded Memory function performed as an }
{ integer. If the error code is not zero, which means the }
{ call failed a simple error procedure is called and the }
{ program terminates. }
{----------------------------------------------------------------}
Type
ST3 = string[3];
ST80 = string[80];
ST5 = string[5];
Registers = record
case integer of
1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: Integer);
2: (AL,AH,BL,BH,CL,DL,DH : Byte);
end;
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;
{--------------------------------------------------------------}
{ Assume we need 1 EMM page for our application. }
{--------------------------------------------------------------}
APPLICATION_PAGE_COUNT = 1;
Var
Regs: Registers;
Emm_Handle,
Page_Frame_Base_Address,
Pages_Needed,
Physical_Page,
Logical_Page,
Offset,
Error_Code,
Pages_EMM_Available,
Total_EMM_Pages,
Available_EMM_Pages: Integer;
Version_Number,
Pages_Number_String: ST3;
Verify: Boolean;
{--------------------------------------------------------------}
{ The function Hex_String converts an integer into a four }
{ character hexadecimal number (string) with leading zeroes. }
{--------------------------------------------------------------}
Function Hex_String (Number: Integer): ST5;
Function Hex_Char (Number: Integer): Char;
Begin
If Number < 10 then
Hex_Char := Char (Number+48)
else
Hex_Char := Char (Number+55);
end; { Function 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; { Function Hex_String }
{--------------------------------------------------------------}
{ The function Emm_Installed checks to see if the Expanded }
{ Memory Manager (EMM) is loaded in memory. It does this by }
{ looking for the string 'EMMXXXX0', which should be located }
{ at 10 bytes from the beginning of the code segment pointed }
{ to by the EMM interrupt, 67h. }
{--------------------------------------------------------------}
Function Emm_Installed: Boolean;
Var
Emm_Device_Name : string[8];
Int_67_Device_Name : string[8];
Position : integer;
Regs : registers;
Begin
Int_67_Device_Name := '';
Emm_Device_Name := 'EMMXXXX0';
with Regs do
Begin
{------------------------------------------------------}
{ Get the code segment pointed to by interrupt 67h, }
{ the EMM interrupt by using DOS function 35h. }
{ (get interrupt vector) }
{------------------------------------------------------}
AH := $35;
AL := EMM_INT;
Intr (DOS_int,Regs);
{------------------------------------------------------}
{ The ES pseudo-register contains the segment }
{ address pointed to by interrupt 67h. Create an }
{ eight character string from the eight successive }
{ bytes at address ES:$000A (10 bytes from ES) }
{------------------------------------------------------}
For Position := 0 to 7 do
Int_67_Device_Name :=
Int_67_Device_Name+Chr (mem[ES:Position+$0A]);
Emm_Installed := True;
{------------------------------------------------------}
{ If the string is the EMM manager signature, }
{ 'EMMXXXX0', then EMM is installed and ready for }
{ use. If not, then EMM is not present. }
{------------------------------------------------------}
If Int_67_Device_Name <> Emm_Device_Name
then Emm_Installed := False;
end; { with Regs do }
end; { Function Emm_Installed }
{--------------------------------------------------------------}
{ This function returns the total number of EMM pages present }
{ in the system, and the number of EMM pages that are }
{ available for our use }
{--------------------------------------------------------------}
Function EMM_Pages_Available
(Var Total_EMM_Pages, Pages_Available: Integer): Integer;
Var
Regs: Registers;
Begin
with Regs do
Begin
{------------------------------------------------------}
{ Get the number of currently unallocated pages and }
{ the total numebr of pages in the system from EMM. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = get unallocated page count function }
{------------------------------------------------------}
AH := Get_Unallocated_Page_Count;
intr (EMM_INT, Regs);
{------------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ BX = currently unallocated pages }
{ DX = total pages in the system }
{ AH = status }
{------------------------------------------------------}
Pages_Available := BX;
Total_EMM_Pages := DX;
EMM_Pages_Available := AH;
end;
end; { EMM_Pages_Available }
{--------------------------------------------------------------}
{ This function requests the specified number of pages }
{ from the EMM. }
{--------------------------------------------------------------}
Function Allocate_Expanded_Memory_Pages
(Pages_Needed: Integer; Var Handle: Integer): Integer;
Var
Regs: Registers;
Begin
with Regs do
Begin
{------------------------------------------------------}
{ Allocate the specified number of pages from EMM. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = allocate pages function. }
{ BX = number of pages to allocate. }
{------------------------------------------------------}
AH := Allocate_Pages;
BX := Pages_Needed;
intr (EMM_INT,Regs);
{------------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ DX = EMM handle }
{ AH = status }
{------------------------------------------------------}
Handle := DX;
Allocate_Expanded_Memory_Pages := AH;
end;
end; { Function Allocate_Expanded_Memory_Pages }
{--------------------------------------------------------------}
{ This function maps a logical page allocated by the }
{ Allocate_Expanded_Memory_Pages function into one of the }
{ four physical pages. }
{--------------------------------------------------------------}
Function Map_Expanded_Memory_Pages
(Handle, Logical_Page, Physical_Page: Integer): Integer;
Var
Regs: Registers;
Begin
with Regs do
Begin
{------------------------------------------------------}
{ Map a logical page at physical page 0. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = map page function }
{ DX = handle }
{ BX = logical page number }
{ AL = physical page number }
{------------------------------------------------------}
AH := Map_Pages;
DX := Handle;
BX := Logical_Page;
AL := Physical_Page;
Intr (EMM_INT, Regs);
{------------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ AH = status }
{------------------------------------------------------}
Map_Expanded_Memory_Pages := AH;
end; { with Regs do }
end; { Function Map_Expanded_Memory_Pages }
{--------------------------------------------------------------}
{ This function gets the physical address of the EMM page }
{ frame we are using. The address returned is the segment }
{ of the page frame. }
{--------------------------------------------------------------}
Function Get_Page_Frame_Base_Address
(Var Page_Frame_Address: Integer): Integer;
Var
Regs: Registers;
Begin
with Regs do
Begin
{------------------------------------------------------}
{ Get the page frame segment address from EMM. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = get page frame segment function }
{------------------------------------------------------}
AH := Get_Page_Frame;
intr (EMM_INT,Regs);
{------------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ BX = page frame segment address }
{ AH = status }
{------------------------------------------------------}
Page_Frame_Address := BX;
Get_Page_Frame_Base_Address := AH;
end; { with Regs do }
end; { Function Get_Page_Frame_Base_Address }
{--------------------------------------------------------------}
{ This function releases the EMM memory pages allocated to }
{ us, back to the EMM memory pool. }
{--------------------------------------------------------------}
Function Deallocate_Expanded_Memory_Pages
(Handle: Integer): Integer;
Var
Regs: Registers;
Begin
with Regs do
Begin
{------------------------------------------------------}
{ Deallocate the pages allocated to an EMM handle. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = deallocate pages function }
{ DX = EMM handle }
{------------------------------------------------------}
AH := DEALLOCATE_PAGES;
DX := Emm_Handle;
Intr (EMM_INT,Regs);
{------------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ AH = status }
{------------------------------------------------------}
Deallocate_Expanded_Memory_Pages := AH;
end; { with Regs do }
end; { Function Deallocate_Expanded_Memory_Pages }
{--------------------------------------------------------------}
{ This function returns the version number of the EMM as }
{ a 3 character string. }
{--------------------------------------------------------------}
Function Get_Version_Number (Var Version_String: ST3): Integer;
Var
Regs: Registers;
Integer_Part, Fractional_Part: Char;
Begin
with Regs do
Begin
{------------------------------------------------------}
{ Get the version of EMM. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = get EMM version function }
{------------------------------------------------------}
AH := GET_VERSION;
Intr (EMM_INT,Regs);
{------------------------------------------------------}
{ If the version numebr was returned OK then }
{ convert it to a 3 character string. }
{------------------------------------------------------}
If AH=STATUS_OK then
Begin
{--------------------------------------------------}
{ The upper four bits of AH are the integer }
{ portion of the version number, the lower four }
{ bits are the fractional portion. Convert the }
{ integer value to ASCII by adding 48. }
{--------------------------------------------------}
Integer_Part := Char (AL shr 4 + 48);
Fractional_Part := Char (AL and $F + 48);
Version_String := Integer_Part + '.' + Fractional_Part;
end; { If AH=STATUS_OK }
{------------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ AH = status }
{------------------------------------------------------}
Get_Version_Number := AH;
end; { with Regs do }
end; { Function Get_Version_Number }
{--------------------------------------------------------------}
{ This procedure prints an error message passed by the }
{ caller, prints the error code passed by the caller in hex, }
{ and then terminates the program with the an error level }
{ of 1. }
{--------------------------------------------------------------}
Procedure Error (Error_Message: ST80; Error_Number: Integer);
Begin
Writeln (Error_Message);
Writeln (' Error_Number = ',Hex_String (Error_Number));
Writeln ('EMM test program aborting.');
Halt (1);
end; { Procedure Error_Message }
{----------------------------------------------------------------}
{ This program is an example of the basic EMM functions that }
{ you need in order to use EMM memory with Turbo Pascal. }
{----------------------------------------------------------------}
Begin
ClrScr;
Window (5,2,77,22);
{--------------------------------------------------------------}
{ Determine if the Expanded Memory Manager is installed, If }
{ not, then terminate 'main' with an ErrorLevel code of 1. }
{--------------------------------------------------------------}
If not (Emm_Installed) then
Begin
Writeln ('The LIM Expanded Memory Manager is not installed.');
Halt (1);
end
else
Begin
{ Get the version number and display it }
Error_Code := Get_Version_Number (Version_Number);
If Error_Code <> STATUS_OK then
Error ('Error trying to get the EMM version number ', Error_code)
else
Writeln ('LIM Expanded Memory Manager, version ',
Version_Number,' is ready for use.');
end;
Writeln;
{--------------------------------------------------------------}
{ Determine if there are enough expanded memory pages for }
{ this application. }
{--------------------------------------------------------------}
Pages_Needed := APPLICATION_PAGE_COUNT;
Error_Code := EMM_Pages_Available (Total_EMM_Pages,
Available_EMM_Pages);
If Error_Code <> STATUS_OK then
Error ('Error trying to determine the number of EMM pages available.',
Error_code);
Writeln ('There are a total of ', Total_EMM_Pages,
' expanded memory pages present in this system.');
Writeln (' ', Available_EMM_Pages,
' of those pages are available for use.');
Writeln;
{--------------------------------------------------------------}
{ If there is an insufficient number of pages for our }
{ application, then report the error and terminate the EMM }
{ example program. }
{--------------------------------------------------------------}
If Pages_Needed > Available_EMM_Pages then
Begin
Str (Pages_Needed, Pages_Number_String);
Error ('We need ' + Pages_Number_String+
' EMM pages. There are not that many available.',
Error_Code);
end; { Pages_Needed > Available_EMM_Pages }
{--------------------------------------------------------------}
{ Allocate expanded memory pages for our use. }
{--------------------------------------------------------------}
Error_Code :=
Allocate_Expanded_Memory_Pages (Pages_Needed, Emm_Handle);
Str (Pages_Needed,Pages_Number_String);
If Error_Code <> STATUS_OK then
Error ('EMM test program failed trying to allocate '
+ Pages_Number_String
+ ' pages for usage.',Error_Code);
Writeln (APPLICATION_PAGE_COUNT,
' EMM page(s) allocated for the EMM test program.');
Writeln;
{--------------------------------------------------------------}
{ Map in the required logical pages to the physical pages }
{ given to us, in this case just one page. }
{--------------------------------------------------------------}
Logical_Page := 0;
Physical_Page := 0;
Error_Code := Map_Expanded_Memory_Pages (Emm_Handle,
Logical_Page,
Physical_Page);
If Error_Code <> STATUS_OK then
Error ('EMM test program failed trying to map '
+ 'logical pages into physical pages.',
Error_Code);
Writeln ('Logical Page ',
Logical_Page,
' successfully mapped into Physical Page ',
Physical_Page);
Writeln;
{--------------------------------------------------------------}
{ Get the expanded memory page frame address. }
{--------------------------------------------------------------}
Error_Code := Get_Page_Frame_Base_Address (Page_Frame_Base_Address);
If Error_Code <> STATUS_OK then
Error ('EMM test program unable to get the base Page'
+ ' Frame Address.',
Error_Code);
Writeln ('The base address of the EMM page frame is = '
+ Hex_String (Page_Frame_Base_Address));
Writeln;
{--------------------------------------------------------------}
{ Write a test pattern to expanded memory. }
{--------------------------------------------------------------}
For Offset := 0 to 16382 do
Begin
Mem[Page_Frame_Base_Address:Offset] := Offset mod 256;
end;
{--------------------------------------------------------------}
{ Make sure that what is in EMM memory is what was just }
{ written. }
{--------------------------------------------------------------}
Writeln ('Testing EMM memory.');
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 (Offset <= 16382) and (Verify = True) }
{--------------------------------------------------------------}
{ If what we read does not match what was written then }
{ we have an error. }
{--------------------------------------------------------------}
If not Verify then
Error ('What was written to EMM memory was not found during '
+ 'memory verification test.',
0);
Writeln ('EMM memory test successful.');
Writeln;
{--------------------------------------------------------------}
{ Return the expanded memory pages given to us back to the }
{ EMM memory pool before terminating our test program. }
{--------------------------------------------------------------}
Error_Code := Deallocate_Expanded_Memory_Pages (Emm_Handle);
If Error_Code <> STATUS_OK then
Error ('EMM test program was unable to deallocate '
+ 'the EMM pages in use.',
Error_Code);
Writeln (APPLICATION_PAGE_COUNT,
' page(s) deallocated.');
Writeln;
Writeln ('EMM test program completed.');
end.