home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / doc / ems / demos / pasexamp / ems.pas < prev   
Pascal/Delphi Source File  |  1988-04-22  |  23KB  |  527 lines

  1. program EMM_example;
  2. {----------------------------------------------------------------}
  3. {   This program shows you how to use the basic functions of     }
  4. {   the LIM Expanded Memory Specification with Turbo Pascal.     }
  5. {   The program does the following:                              }
  6. {                                                                }
  7. {   1. Makes sure the LIM Expanded Memory Manager (EMM) has      }
  8. {      been installed.                                           }
  9. {   2. Displays the version number of the EMM.                   }
  10. {   3. Determines if there are enough pages (16k blocks) of      }
  11. {      memory for our test program's usage. It then displays     }
  12. {      the total number of EMM pages present in the system,      }
  13. {      and how many are available for our use.                   }
  14. {   4. Requests the desired number of pages from the EMM.        }
  15. {   5. Maps a logical page into one of the physical pages.       }
  16. {   6. Displays the base address of our EMM memory page frame    }
  17. {      Performs a simple read/write test on the EMM memory.      }
  18. {   7. Returns the EMM memory given to us back to the EMM.       }
  19. {   8. Exits                                                     }
  20. {                                                                }
  21. {   All the calls are structured to return the result or error   }
  22. {   code of the Expanded Memory function performed as an         }
  23. {   integer.  If the error code is not zero, which means the     }
  24. {   call failed a simple error procedure is called and the       }
  25. {   program terminates.                                          }
  26. {----------------------------------------------------------------}
  27.  
  28. Type
  29.   ST3  = string[3];
  30.   ST80 = string[80];
  31.   ST5  = string[5];
  32.  
  33.   Registers = record
  34.     case integer of
  35.       1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: Integer);
  36.       2: (AL,AH,BL,BH,CL,DL,DH            : Byte);
  37.     end;
  38.  
  39. Const
  40.   EMM_INT                   = $67;
  41.   DOS_Int                   = $21;
  42.   GET_PAGE_FRAME            = $41;
  43.   GET_UNALLOCATED_PAGE_COUNT= $42;
  44.   ALLOCATE_PAGES            = $43;
  45.   MAP_PAGES                 = $44;
  46.   DEALLOCATE_PAGES          = $45;
  47.   GET_VERSION               = $46;
  48.   STATUS_OK                 = 0;
  49.  
  50.   {--------------------------------------------------------------}
  51.   {   Assume we need 1 EMM page for our application.             }
  52.   {--------------------------------------------------------------}
  53.   APPLICATION_PAGE_COUNT    = 1;
  54.  
  55. Var
  56.   Regs: Registers;
  57.  
  58.   Emm_Handle,
  59.   Page_Frame_Base_Address,
  60.   Pages_Needed,
  61.   Physical_Page,
  62.   Logical_Page,
  63.   Offset,
  64.   Error_Code,
  65.   Pages_EMM_Available,
  66.   Total_EMM_Pages,
  67.   Available_EMM_Pages: Integer;
  68.  
  69.   Version_Number,
  70.   Pages_Number_String: ST3;
  71.  
  72.   Verify: Boolean;
  73.  
  74.   {--------------------------------------------------------------}
  75.   {   The function Hex_String converts an integer into a four    }
  76.   {   character hexadecimal number (string) with leading zeroes. }
  77.   {--------------------------------------------------------------}
  78.   Function Hex_String (Number: Integer): ST5;
  79.     Function Hex_Char (Number: Integer): Char;
  80.       Begin
  81.         If Number < 10 then
  82.           Hex_Char := Char (Number+48)
  83.         else
  84.           Hex_Char := Char (Number+55);
  85.       end; { Function Hex_Char }
  86.  
  87.     Var
  88.       S: ST5;
  89.  
  90.     Begin
  91.       S := '';
  92.       S := Hex_Char ((Number shr 1) div 2048);
  93.       Number := (((Number shr 1) mod 2048) shl 1) + (Number and 1);
  94.       S := S+Hex_Char (Number div 256);
  95.       Number := Number mod 256;
  96.       S := S+Hex_Char (Number div 16);
  97.       Number := Number mod 16;
  98.       S := S+Hex_Char (Number);
  99.       Hex_String := S+'h';
  100.   end; { Function Hex_String }
  101.  
  102.  
  103.   {--------------------------------------------------------------}
  104.   {   The function Emm_Installed checks to see if the Expanded   }
  105.   {   Memory Manager (EMM) is loaded in memory. It does this by  }
  106.   {   looking for the string 'EMMXXXX0', which should be located }
  107.   {   at 10 bytes from the beginning of the code segment pointed }
  108.   {   to by the EMM interrupt, 67h.                              }
  109.   {--------------------------------------------------------------}
  110.   Function Emm_Installed: Boolean;
  111.     Var
  112.       Emm_Device_Name       : string[8];
  113.       Int_67_Device_Name    : string[8];
  114.       Position              : integer;
  115.       Regs                  : registers;
  116.  
  117.     Begin
  118.       Int_67_Device_Name := '';
  119.       Emm_Device_Name    := 'EMMXXXX0';
  120.       with Regs do
  121.         Begin
  122.           {------------------------------------------------------}
  123.           {   Get the code segment pointed to by interrupt 67h,  }
  124.           {   the EMM interrupt by using DOS function 35h.       }
  125.           {   (get interrupt vector)                             }
  126.           {------------------------------------------------------}
  127.           AH := $35;
  128.           AL := EMM_INT;
  129.           Intr (DOS_int,Regs);
  130.           {------------------------------------------------------}
  131.           {   The ES pseudo-register contains the segment        }
  132.           {   address pointed to by interrupt 67h.  Create an    }
  133.           {   eight character string from the eight successive   }
  134.           {   bytes at address ES:$000A (10 bytes from ES)       }
  135.           {------------------------------------------------------}
  136.           For Position := 0 to 7 do
  137.             Int_67_Device_Name :=
  138.                     Int_67_Device_Name+Chr (mem[ES:Position+$0A]);
  139.           Emm_Installed := True;
  140.           {------------------------------------------------------}
  141.           {   If the string is the EMM manager signature,        } 
  142.           {   'EMMXXXX0', then EMM is installed and ready for    }
  143.           {   use.  If not, then EMM is not present.             }
  144.           {------------------------------------------------------}
  145.           If Int_67_Device_Name <> Emm_Device_Name
  146.             then Emm_Installed := False;
  147.         end; { with Regs do }
  148.     end;  { Function Emm_Installed }
  149.  
  150.  
  151.   {--------------------------------------------------------------}
  152.   {  This function returns the total number of EMM pages present }
  153.   {  in the system, and the number of EMM pages that are         }
  154.   {  available for our use                                       }
  155.   {--------------------------------------------------------------}
  156.   Function EMM_Pages_Available
  157.     (Var Total_EMM_Pages, Pages_Available: Integer): Integer;
  158.     Var
  159.       Regs: Registers;
  160.  
  161.     Begin
  162.       with Regs do
  163.         Begin
  164.           {------------------------------------------------------}
  165.           {   Get the number of currently unallocated pages and  }
  166.           {   the total numebr of pages in the system from EMM.  }
  167.           {   Load pseudo-registers prior to invoking EMM.       }
  168.           {      AH = get unallocated page count function        }
  169.           {------------------------------------------------------}
  170.           AH := Get_Unallocated_Page_Count;
  171.           intr (EMM_INT, Regs);
  172.           {------------------------------------------------------}
  173.           {   Unload the pseudo-registers after invoking EMM.    }
  174.           {      BX = currently unallocated pages                }
  175.           {      DX = total pages in the system                  }
  176.           {      AH = status                                     }
  177.           {------------------------------------------------------}
  178.           Pages_Available := BX;
  179.           Total_EMM_Pages := DX;
  180.           EMM_Pages_Available := AH;
  181.         end;
  182.     end; { EMM_Pages_Available }
  183.  
  184.  
  185.   {--------------------------------------------------------------}
  186.   {   This function requests the specified number of pages       }
  187.   {   from the EMM.                                              }
  188.   {--------------------------------------------------------------}
  189.   Function Allocate_Expanded_Memory_Pages
  190.     (Pages_Needed: Integer; Var Handle: Integer): Integer;
  191.     Var
  192.       Regs: Registers;
  193.  
  194.     Begin
  195.       with Regs do
  196.         Begin
  197.           {------------------------------------------------------}
  198.           {   Allocate the specified number of pages from EMM.   }
  199.           {   Load pseudo-registers prior to invoking EMM.       }
  200.           {      AH = allocate pages function.                   }
  201.           {      BX = number of pages to allocate.               }
  202.           {------------------------------------------------------}
  203.           AH := Allocate_Pages;
  204.           BX := Pages_Needed;
  205.           intr (EMM_INT,Regs);
  206.           {------------------------------------------------------}
  207.           {   Unload the pseudo-registers after invoking EMM.    }
  208.           {      DX = EMM handle                                 }
  209.           {      AH = status                                     }
  210.           {------------------------------------------------------}
  211.           Handle := DX;
  212.           Allocate_Expanded_Memory_Pages := AH;
  213.         end;
  214.     end; { Function Allocate_Expanded_Memory_Pages }
  215.  
  216.  
  217.   {--------------------------------------------------------------}
  218.   {   This function maps a logical page allocated by the         }
  219.   {   Allocate_Expanded_Memory_Pages function into one of the    }
  220.   {   four physical pages.                                       }
  221.   {--------------------------------------------------------------}
  222.   Function Map_Expanded_Memory_Pages
  223.     (Handle, Logical_Page, Physical_Page: Integer): Integer;
  224.     Var
  225.       Regs: Registers;
  226.  
  227.     Begin
  228.       with Regs do
  229.         Begin
  230.           {------------------------------------------------------}
  231.           {   Map a logical page at physical page 0.             }
  232.           {   Load pseudo-registers prior to invoking EMM.       }
  233.           {      AH = map page function                          }
  234.           {      DX = handle                                     }
  235.           {      BX = logical page number                        }
  236.           {      AL = physical page number                       }
  237.           {------------------------------------------------------}
  238.           AH := Map_Pages;
  239.           DX := Handle;
  240.           BX := Logical_Page;
  241.           AL := Physical_Page;
  242.           Intr (EMM_INT, Regs);
  243.           {------------------------------------------------------}
  244.           {   Unload the pseudo-registers after invoking EMM.    }
  245.           {      AH = status                                     }
  246.           {------------------------------------------------------}
  247.           Map_Expanded_Memory_Pages := AH;
  248.         end; { with Regs do }
  249.     end; { Function Map_Expanded_Memory_Pages }
  250.  
  251.  
  252.   {--------------------------------------------------------------}
  253.   {   This function gets the physical address of the EMM page    }
  254.   {   frame we are using. The address returned is the segment    }
  255.   {   of the page frame.                                         }
  256.   {--------------------------------------------------------------}
  257.   Function Get_Page_Frame_Base_Address
  258.     (Var Page_Frame_Address: Integer): Integer;
  259.     Var
  260.       Regs: Registers;
  261.  
  262.     Begin
  263.       with Regs do
  264.         Begin
  265.           {------------------------------------------------------}
  266.           {   Get the page frame segment address from EMM.       }
  267.           {   Load pseudo-registers prior to invoking EMM.       }
  268.           {      AH = get page frame segment function            }
  269.           {------------------------------------------------------}
  270.           AH := Get_Page_Frame;
  271.           intr (EMM_INT,Regs);
  272.           {------------------------------------------------------}
  273.           {   Unload the pseudo-registers after invoking EMM.    }
  274.           {      BX = page frame segment address                 }
  275.           {      AH = status                                     }
  276.           {------------------------------------------------------}
  277.           Page_Frame_Address := BX;
  278.           Get_Page_Frame_Base_Address := AH;
  279.          end; { with Regs do }
  280.     end; { Function Get_Page_Frame_Base_Address }
  281.  
  282.  
  283.   {--------------------------------------------------------------}
  284.   {   This function releases the EMM memory pages allocated to   }
  285.   {   us, back to the EMM memory pool.                           }
  286.   {--------------------------------------------------------------}
  287.   Function Deallocate_Expanded_Memory_Pages
  288.     (Handle: Integer): Integer;
  289.     Var
  290.       Regs: Registers;
  291.  
  292.     Begin
  293.       with Regs do
  294.         Begin
  295.           {------------------------------------------------------}
  296.           {   Deallocate the pages allocated to an EMM handle.   }
  297.           {   Load pseudo-registers prior to invoking EMM.       }
  298.           {      AH = deallocate pages function                  }
  299.           {      DX = EMM handle                                 }
  300.           {------------------------------------------------------}
  301.           AH := DEALLOCATE_PAGES;
  302.           DX := Emm_Handle;
  303.           Intr (EMM_INT,Regs);
  304.           {------------------------------------------------------}
  305.           {   Unload the pseudo-registers after invoking EMM.    }
  306.           {      AH = status                                     }
  307.           {------------------------------------------------------}
  308.           Deallocate_Expanded_Memory_Pages := AH;
  309.         end; { with Regs do }
  310.     end;  { Function Deallocate_Expanded_Memory_Pages }
  311.  
  312.  
  313.   {--------------------------------------------------------------}
  314.   {   This function returns the version number of the EMM as     }
  315.   {   a 3 character string.                                      }
  316.   {--------------------------------------------------------------}
  317.   Function Get_Version_Number (Var Version_String: ST3): Integer;
  318.     Var
  319.       Regs: Registers;
  320.       Integer_Part, Fractional_Part: Char;
  321.  
  322.     Begin
  323.       with Regs do
  324.         Begin
  325.           {------------------------------------------------------}
  326.           {   Get the version of EMM.                            }
  327.           {   Load pseudo-registers prior to invoking EMM.       }
  328.           {      AH = get EMM version function                   }
  329.           {------------------------------------------------------}
  330.           AH := GET_VERSION;
  331.           Intr (EMM_INT,Regs);
  332.  
  333.           {------------------------------------------------------}
  334.           {   If the version numebr was returned OK then         }
  335.           {      convert it to a 3 character string.             }
  336.           {------------------------------------------------------}
  337.           If AH=STATUS_OK then
  338.             Begin
  339.               {--------------------------------------------------}
  340.               {   The upper four bits of AH are the integer      }
  341.               {   portion of the version number, the lower four  }
  342.               {   bits are the fractional portion. Convert the   }
  343.               {   integer value to ASCII by adding 48.           }
  344.               {--------------------------------------------------}
  345.               Integer_Part    := Char (AL shr 4  + 48);
  346.               Fractional_Part := Char (AL and $F + 48);
  347.               Version_String  := Integer_Part + '.' + Fractional_Part;
  348.             end; { If AH=STATUS_OK }
  349.           {------------------------------------------------------}
  350.           {   Unload the pseudo-registers after invoking EMM.    }
  351.           {      AH = status                                     }
  352.           {------------------------------------------------------}
  353.           Get_Version_Number := AH;
  354.         end; { with Regs do }
  355.     end; { Function Get_Version_Number }
  356.  
  357.  
  358.   {--------------------------------------------------------------}
  359.   {   This procedure prints an error message passed by the       }
  360.   {   caller, prints the error code passed by the caller in hex, }
  361.   {   and then terminates the program with the an error level    }
  362.   {   of 1.                                                      }
  363.   {--------------------------------------------------------------}
  364.   Procedure Error (Error_Message: ST80; Error_Number: Integer);
  365.     Begin
  366.       Writeln (Error_Message);
  367.       Writeln ('  Error_Number = ',Hex_String (Error_Number));
  368.       Writeln ('EMM test program aborting.');
  369.       Halt (1);
  370.     end; { Procedure Error_Message }
  371.  
  372.  
  373. {----------------------------------------------------------------}
  374. {   This program is an example of the basic EMM functions that   }
  375. {   you need in order to use EMM memory with Turbo Pascal.       }
  376. {----------------------------------------------------------------}
  377. Begin
  378.   ClrScr;
  379.   Window (5,2,77,22);
  380.  
  381.   {--------------------------------------------------------------}
  382.   {   Determine if the Expanded Memory Manager is installed, If  }
  383.   {   not, then terminate 'main' with an ErrorLevel code of 1.   }
  384.   {--------------------------------------------------------------}
  385.   If not (Emm_Installed) then
  386.     Begin
  387.       Writeln ('The LIM Expanded Memory Manager is not installed.');
  388.       Halt (1);
  389.     end
  390.   else
  391.     Begin
  392.       { Get the version number and display it }
  393.       Error_Code := Get_Version_Number (Version_Number);
  394.       If Error_Code <> STATUS_OK then
  395.         Error ('Error trying to get the EMM version number ', Error_code)
  396.       else
  397.         Writeln ('LIM Expanded Memory Manager, version ',
  398.                 Version_Number,' is ready for use.');
  399.     end;
  400.   Writeln;
  401.  
  402.   {--------------------------------------------------------------}
  403.   {   Determine if there are enough expanded memory pages for    }
  404.   {   this application.                                          }
  405.   {--------------------------------------------------------------}
  406.   Pages_Needed := APPLICATION_PAGE_COUNT;
  407.   Error_Code   := EMM_Pages_Available (Total_EMM_Pages,
  408.                                        Available_EMM_Pages);
  409.   If Error_Code <> STATUS_OK then
  410.     Error ('Error trying to determine the number of EMM pages available.',
  411.           Error_code);
  412.  
  413.   Writeln ('There are a total of ', Total_EMM_Pages,
  414.            ' expanded memory pages present in this system.');
  415.   Writeln ('  ', Available_EMM_Pages,
  416.            ' of those pages are available for use.');
  417.   Writeln;
  418.  
  419.   {--------------------------------------------------------------}
  420.   {   If there is an insufficient number of pages for our        }
  421.   {   application, then report the error and terminate the EMM   }
  422.   {   example program.                                           }
  423.   {--------------------------------------------------------------}
  424.   If Pages_Needed > Available_EMM_Pages then
  425.     Begin
  426.       Str (Pages_Needed, Pages_Number_String);
  427.       Error ('We need ' + Pages_Number_String+
  428.              ' EMM pages. There are not that many available.',
  429.              Error_Code);
  430.     end; { Pages_Needed > Available_EMM_Pages }
  431.  
  432.   {--------------------------------------------------------------}
  433.   {   Allocate expanded memory pages for our use.                }
  434.   {--------------------------------------------------------------}
  435.   Error_Code := 
  436.     Allocate_Expanded_Memory_Pages (Pages_Needed, Emm_Handle);
  437.   Str (Pages_Needed,Pages_Number_String);
  438.   If Error_Code <> STATUS_OK then
  439.     Error ('EMM test program failed trying to allocate '
  440.            + Pages_Number_String
  441.            + ' pages for usage.',Error_Code);
  442.   Writeln (APPLICATION_PAGE_COUNT,
  443.            ' EMM page(s) allocated for the EMM test program.');
  444.   Writeln;
  445.  
  446.   {--------------------------------------------------------------}
  447.   {   Map in the required logical pages to the physical pages    }
  448.   {   given to us, in this case just one page.                   }   
  449.   {--------------------------------------------------------------}
  450.   Logical_Page  := 0;
  451.   Physical_Page := 0;
  452.   Error_Code := Map_Expanded_Memory_Pages (Emm_Handle,
  453.                                            Logical_Page,
  454.                                            Physical_Page);
  455.   If Error_Code <> STATUS_OK then
  456.     Error ('EMM test program failed trying to map '
  457.            + 'logical pages into physical pages.',
  458.            Error_Code);
  459.  
  460.   Writeln ('Logical Page ',
  461.            Logical_Page,
  462.            ' successfully mapped into Physical Page ',
  463.            Physical_Page);
  464.   Writeln;
  465.  
  466.   {--------------------------------------------------------------}
  467.   {   Get the expanded memory page frame address.                }
  468.   {--------------------------------------------------------------}
  469.   Error_Code := Get_Page_Frame_Base_Address (Page_Frame_Base_Address);
  470.   If Error_Code <> STATUS_OK then
  471.     Error ('EMM test program unable to get the base Page'
  472.            + ' Frame Address.',
  473.            Error_Code);
  474.   Writeln ('The base address of the EMM page frame is = '
  475.            + Hex_String (Page_Frame_Base_Address));
  476.   Writeln;
  477.  
  478.   {--------------------------------------------------------------}
  479.   {   Write a test pattern to expanded memory.                   }
  480.   {--------------------------------------------------------------}
  481.   For Offset := 0 to 16382 do
  482.     Begin
  483.       Mem[Page_Frame_Base_Address:Offset] := Offset mod 256;
  484.     end;
  485.  
  486.   {--------------------------------------------------------------}
  487.   {   Make sure that what is in EMM memory is what was just      }
  488.   {   written.                                                   }
  489.   {--------------------------------------------------------------}
  490.   Writeln ('Testing EMM memory.');
  491.  
  492.   Offset := 1;
  493.   Verify := True;
  494.   while (Offset <= 16382) and (Verify = True) do
  495.     Begin
  496.       If Mem[Page_Frame_Base_Address:Offset] <> Offset mod 256 then
  497.         Verify := False;
  498.       Offset := Succ (Offset);
  499.     end;  { while (Offset <= 16382) and (Verify = True) }
  500.  
  501.   {--------------------------------------------------------------}
  502.   {   If what we read does not match what was written then       }
  503.   {     we have an error.                                        }
  504.   {--------------------------------------------------------------}
  505.   If not Verify then
  506.     Error ('What was written to EMM memory was not found during '
  507.            + 'memory verification  test.',
  508.            0);
  509.   Writeln ('EMM memory test successful.');
  510.   Writeln;
  511.  
  512.   {--------------------------------------------------------------}
  513.   {   Return the expanded memory pages given to us back to the   }
  514.   {   EMM memory pool before terminating our test program.       }
  515.   {--------------------------------------------------------------}
  516.   Error_Code := Deallocate_Expanded_Memory_Pages (Emm_Handle);
  517.   If Error_Code <> STATUS_OK then
  518.     Error ('EMM test program was unable to deallocate '
  519.            + 'the EMM pages in use.',
  520.            Error_Code);
  521.   Writeln (APPLICATION_PAGE_COUNT,
  522.            ' page(s) deallocated.');
  523.   Writeln;
  524.   Writeln ('EMM test program completed.');
  525.  
  526. end.
  527.