home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / b / bc3.zip / README < prev    next >
Text File  |  1992-02-17  |  30KB  |  725 lines

  1.  
  2.  (C) Copyright 1992, Qualitas, Inc. All Rights Reserved
  3.  
  4.  Qualitas C/C++ Libraries for DPMI
  5.  
  6.  ** Contents of this file **
  7.  
  8.  1. Introduction
  9.  2. Requirements
  10.  3. Limitations
  11.  4. Building the Example Programs
  12.  5. Building the DPMI libraries
  13.  6. Using the C library
  14.  7. Using the C++ class library
  15.  
  16.  **********************************************************************
  17.  
  18.  1. Introduction
  19.  
  20.  The Qualitas C/C++ Libraries for DPMI provide the C/C++ programmer with
  21.  easy access to DPMI.  The purpose of the libraries is to allow developers
  22.  to gain familiarity with DPMI concepts, to aid in understanding of how
  23.  DPMI can be used, and to serve as a platform for experimentation with
  24.  DPMI hosts via the creation of small model C/C++ applications.
  25.  
  26.  The directories are structured as follows:
  27.  
  28.                      top
  29.                       |
  30.       +------------------+--------+---------+------------------+
  31.       |             |            |           |
  32.      BC2            BC3               MSC6         MSC7
  33.       |             |            |           |
  34.   +-------+------+   +-------+------+    +-------+------+   +-------+------+ 
  35.   |    |    |     |   |      |    |    |    |    |      |    |   |    |    |      |
  36.  LIB   |    |     |  LIB      |    |    |  LIB   |      |    |  LIB    |    |      |
  37.     LIBSRC  |     |     LIBSRC  |    |      LIBSRC  |    |     LIBSRC  |      |
  38.      INCLUDE |        INCLUDE |           INCLUDE |      INCLUDE |
  39.           EXAMPLES         EXAMPLES        EXAMPLES          EXAMPLES
  40.  
  41.  For convenience of installation, the distribution provides a copy of the
  42.  source code for the libraries and examples in each compiler directory.
  43.  The primary differences between compiler directories are (1) the makefiles
  44.  differ, and (2) some of the source code distributed with the compilers
  45.  has been modified for operation in conjunction with the DPMI libraires,
  46.  and those modules are included in their respective directories.
  47.  
  48.     \        this README file
  49.     .\MSC7LIB    Microsoft C/C++ 7.0 support
  50.     .\MSC6LIB    Microsoft C 6.0 support
  51.     .\BC3LIB    Borland C/C++ 3.0 support
  52.     .\BC2LIB    Borland C/C++ 2.0 support
  53.     .\xxx\LIBSRC    Source code for the DPMI libraries
  54.     .\xxx\INCLUDE    Header files required for source and examples
  55.     .\xxx\EXAMPLES    Source code for the example programs
  56.     
  57.  For example, to install the DPMI libraries for Borland C++ version 3.0,
  58.  use the following commands:
  59.  
  60.     C> md DPMILIBS
  61.     C> cd DPMILIBS
  62.     C:\DPMILIBS> cd a:\BC3LIB
  63.     C:\DPMILIBS> xcopy a: /s
  64.  
  65.  **********************************************************************
  66.  
  67.  2. Requirements
  68.  
  69.  The requirements depend upon which C compiler you are using:
  70.  
  71.  Compiler    Processor    Assembler    Linker        Librarian
  72.  --------    ---------    ---------    ------        ---------
  73.  Microsoft v7    80386        MASM 6.0    LINK 5.30    LIB 3.20
  74.  Microsoft v6    80286        MASM 6.0+5.1    LINK 5.10    LIB 3.18
  75.  Borland v3    80286        TASM 3.0    TLINK 5.0    TLIB 3.02
  76.  Borland v2    80286        TASM 2.5    TLINK 4.0    TLIB 3.02
  77.  
  78.  NOTE:    The librarian and assembler are only required if you wish to 
  79.     rebuild the libraries.    They are not required to build the
  80.     examples or other applications.
  81.  
  82.  Each compiler requires the small model libraries.  The Microsoft compilers
  83.  require the include files for the startup source to rebuild the DPMI
  84.  libraries.
  85.  
  86.  **********************************************************************
  87.  
  88.  3. Limitations
  89.  
  90.  * Only small model is supported.  It is possible, however, to use
  91.    far pointers that are dynamically created, for example, by using
  92.    the MK_FP macro.  Statically initialized far pointers will work
  93.    only if they refer to the default code segment or the default data
  94.    segment.
  95.  
  96.  * Floating point is not supported.  The run-time requirements create
  97.    complications which are beyond the scope of this implementation.
  98.  
  99.  * Errors may result from use of run time library functions that require
  100.    running clean-up routines at exit time, if such clean-up routines 
  101.    utilize real mode far pointers created prior to entering protected mode.
  102.  
  103.  **********************************************************************
  104.  
  105.  4. Building the Example Programs
  106.  
  107.  The .\EXAMPLES directory contains the following programs:
  108.  
  109.  * HELLO.C   A simple C program that illustrates how to enter 
  110.          protected mode, and how to call the DPMI C library.
  111.  * QSORT.C   A program that sorts stdin to stdout. It uses DPMI to
  112.          allocate buffers, which enables it to sort very
  113.          large files in memory.
  114.  * XMEM.CPP  A C++ program that illustrates the use of the classes in
  115.          the DPMI class libraries that are related to memory usage.
  116.  * XINTR.CPP A C++ program that illustrates the use of the classes in
  117.          the DPMI class libraries that are related to interrupt handling.
  118.  * XREAL.CPP A C++ program that illustrates the use of the classes in
  119.          the DPMI class libraries that are related to calling real
  120.          mode functions and real mode call-backs.
  121.  * XCEPT.CPP A C++ program that illustrates the use of the classes in
  122.          the DPMI class libraries that are related to exception handling.
  123.  
  124.  More detail about using the libraries and classes is found below.
  125.  
  126.  
  127.  ** To build the examples with Microsoft C 7.0
  128.  
  129.     - Your current directory must be the MSC7\EXAMPLES directory.
  130.     - CL and LINK for MS C 7.0 must be on your path.
  131.     - Your INCLUDE and LIB environment variables must be set for
  132.       a normal MS C 7.0 build.
  133.     - Issue the command NMAKE.
  134.  
  135.  ** To build the examples with Microsoft C 6.0
  136.  
  137.     NOTE: the C++ examples are not built for MS C 6.0
  138.  
  139.     - Your current directory must be the MSC6\EXAMPLES directory.
  140.     - CL and LINK for MS C 6.0 must be on your path.
  141.     - Your INCLUDE and LIB environment variables must be set for
  142.       a normal MS C 6.0 build.
  143.     - Issue the command NMAKE.
  144.  
  145.  ** To build the examples with Borland C++ 3.0
  146.  
  147.     - Your current directory must be the BC3\EXAMPLES directory.
  148.     - BCC and TLINK for BC++ 3.0 must be on your path.
  149.     - The BC3LIB variable in the MAKEFILE must be set to the
  150.       directory where your Borland C++ libraries
  151.       reside.  Edit MAKEFILE and locate the BC3LIB line.
  152.       Change the right hand side of the statement
  153.       as needed for your environment.
  154.     - Issue the command MAKE.
  155.  
  156.  ** To build the examples with Borland C++ 2.0
  157.  
  158.     - Your current directory must be the EXAMPLES directory.
  159.     - BCC and TLINK for BC++ 2.0 must be on your path.
  160.     - The BC2LIB variable in the MAKEFILE must be set to the
  161.       directory where your Borland C++ libraries
  162.       reside.  Edit MAKEFILE and locate the BC2LIB line.
  163.       Change the right hand side of the statement
  164.       as needed for your environment.
  165.     - Issue the command MAKE.
  166.  
  167.  **********************************************************************
  168.  
  169.  5. Building the DPMI libraries
  170.  
  171.  It is not necessary to rebuild the libraries in order to build the examples
  172.  or to build other applications.  However, in the event you wish to modify
  173.  the library source code, the following instructions are provided for 
  174.  rebuilding the libraries:
  175.  
  176.  ** To build the libraries with Microsoft C 7.0
  177.  
  178.     - Your current directory must be the MSC7\LIBSRC directory.
  179.     - CL, MASM (v6.0) and LINK for MS C 7.0 must be on your path.
  180.     - Your INCLUDE and LIB environment variables must be set for
  181.       a normal MS C 7.0 build.
  182.     - The C7DIR variable in the makefile must
  183.       be set to the directory where your Microsoft C++ distribution
  184.       resides.  Edit MAKEFILE and locate the C7DIR= line
  185.       Change the right hand side of the statement
  186.       as needed for your environment.
  187.     - Issue the command NMAKE.
  188.  
  189.  ** To build the libraries with Microsoft C 6.0
  190.  
  191.     NOTE: the C++ libraries are not built for MS C 6.0
  192.  
  193.     - Your current directory must be the MSC6\LIBSRC directory.
  194.     - CL and LINK for MS C 6.0 must be on your path.
  195.     - Your INCLUDE and LIB environment variables must be set for
  196.       a normal MS C 6.0 build.
  197.     - The C6DIR variable in the MAKEFILE must
  198.       be set to the directory where your Microsoft C distribution
  199.       resides.  Edit MAKEFILE and locate the C6DIR= line.
  200.       Change the right hand side of the statement
  201.       as needed for your environment.
  202.     - The ASM51 variable in the MAKEFILE must be set for the
  203.       5.1 version of MASM in order to assemble the MS C 6.0 startup code.
  204.     - Issue the command NMAKE.
  205.  
  206.  
  207.  ** To build the libraries with Borland C++ 3.0
  208.  
  209.     - Your current directory must be the BC3\LIBSRC directory.
  210.     - BCC, TASM, and TLINK for BC++ 3.0 must be on your path.
  211.     - Issue the command MAKE.
  212.  
  213.  ** To build the libraries with Borland C++ 2.0
  214.  
  215.     - Your current directory must be the LIBSRC directory.
  216.     - BCC, TASM, and TLINK for BC++ 2.0 must be on your path.
  217.     - Issue the command MAKE.
  218.  
  219.  
  220.  **********************************************************************
  221.  
  222.  6. Using the C Library
  223.  
  224.  There is roughly a one-to-one mapping between the set of DPMI version 0.9 
  225.  functions and the entry points of the DPMI C library.    A copy of the
  226.  DPMI specification may be a useful reference.
  227.  
  228.  A set of three higher level calls is provided for simplified memory
  229.  management. DPMImalloc(), DPMIresize(), and DPMIfree() provide a means
  230.  to allocate and address blocks of memory allocated from DPMI.    These
  231.  calls are implemented using lower level calls of the library.    Refer to
  232.  DPMIMALL.C in the LIBSRC directory to see how.
  233.  
  234.  Definitions for the C library are found in INCLUDE\DPMI.H.  This file
  235.  contains structure definitions, function prototypes, and descriptions
  236.  of each call.
  237.  
  238.  Two example programs are provided in the EXAMPLES directory. HELLO.C shows
  239.  basic usage: how to enter protected mode and call a library routine.
  240.  QSORT.C is a useful utillity for sorting large files, which is built
  241.  using the DPMImalloc family of memory management routines.
  242.  
  243.  
  244.  **********************************************************************
  245.  
  246.  7. Using the C++ Class Library
  247.  
  248.  
  249.  The class library provides a set of C++ classes that abstract several
  250.  important DPMI objects.  The header files provide descriptions and
  251.  brief examples on using the classes.
  252.  
  253.  Definitions for the DPMI classes are contained in these header files,
  254.  found in the INCLUDE directory:
  255.  
  256.     DPMIHOST.H    DPMI host class
  257.     SEGMENT.H    All memory related classes
  258.     REALPROC.H    Real procedure class
  259.     REALINT.H    Real interrupt class
  260.     CALLBACK.H    Real mode call-back class
  261.     DPMIINT.H    Interrupt handler classes
  262.     EXCEPTIO.H    Processor exception handler class
  263.  
  264.  
  265.  General note: Many of the constructors make calls to DPMI.  Since the
  266.  constructors for statically allocated class instances are called prior
  267.  to main(), declaring instances from the DPMI classes statically may
  268.  result in attempting to call DPMI prior to entering protected mode,
  269.  which probably will cause a system crash.  Therefore, DPMI objects
  270.  should be created dynamically, either as automatics (on a function's
  271.  local stack frame) or with the new operator.  It is certainly allowable
  272.  to statically allocate pointers to DPMI objects, and initialize them
  273.  after entering protected mode in order to gain global addressability.
  274.  
  275.  *--------------------------------------------------------------------
  276.  
  277.  Header File: DPMIHOST.H  See examples XMEM, XREAL, XCEPT, XINTR
  278.  
  279.  Classes    Members
  280.  -------    -------
  281.  DPMIhost
  282.         DPMIhost        Constructor; checks presence of    a
  283.                     DPMI host, and gathers needed 
  284.                     host information.
  285.         getStatus        Used to verify detection of DPMI host
  286.         enterProtectedMode    Makes the initial switch into 
  287.                     protected mode.
  288.         getProcessor        Returns processor code
  289.         getVersion        Returns major and minor version.
  290.         getSelectorDelta    Returns delta between consecutive
  291.                     selectors.
  292.  
  293.  When you declare a DPMIhost object in your program, the constructor tests
  294.  for the presence of a DPMI host on your system.  If found, the constructor
  295.  collects information from the host needed for the switch into protected mode.
  296.  
  297.  You can determine the success or failure of the constructor by calling the
  298.  getStatus member, which returns DPMIok if the constructor found a DPMI host
  299.  and was successfully initialized.  The members getProcessor, getVersion,
  300.  and getSelectorDelta simply return the appropriate host parameters.
  301.  
  302.  You use the member enterProtectedMode for the initial switch into protected
  303.  mode, and after that it should not be called.    It first allocates a block
  304.  of DOS memory to satisfy the host's private data area requirements.  It then
  305.  calls the mode switch entry point obtained by the constructor.     When this
  306.  returns, the processor is running in protected mode.  Finally, this member
  307.  relocates the executable image for protected mode operation (see 
  308.  Implementation Notes for details).  The enterProtectedMode member returns
  309.  TRUE if the processor is successfully switched to protected mode. 
  310.  *--------------------------------------------------------------------
  311.  
  312.  Header File: SEGMENT.H     See example XMEM
  313.  
  314.  Classes    Members
  315.  -------    -------
  316.  Block
  317.         Block            Constructor; allocates raw block
  318.                     of memory from DPMI.
  319.         ~Block            Destructor; release block to DPMI
  320.         setSize            Resize function reallocates block.
  321.         blockHandle        Returns block handle.
  322.         blockSize        Returns block size.
  323.         blockBase        Returns base linear address.
  324.  
  325.  AbstractSegment
  326.         segmentSize        Returns size of segment.
  327.         segmentBase        Returns base of segment.
  328.         resize            Resizes segment.
  329.         move            Changes segment base.
  330.         operator+        Adds a segment property.
  331.         operator-        Removes a segment property.
  332.         queryProp        Tests for segment property.
  333.  Segment
  334.  : AbstractSegment
  335.         Segment(void)        Generic constructor.
  336.         Segment(selector_t)    Specific descriptor.
  337.         Segment(AbstractSegment&) Alias to existing segment.
  338.         ~Segment(void);        Releases descriptor to DPMI.
  339.  
  340.  
  341.  CommonRealSegment
  342.  : AbstractSegment
  343.         CommonRealSegment    Constructor
  344.  
  345.  DOSMemory
  346.  : AbstractSegment
  347.         DOSMemory        Constructor
  348.         ~DOSMemory        Destructor
  349.  
  350.  
  351.  HugeSegment
  352.  : AbstractSegment
  353.         HugeSegment        Constructor
  354.         ~HugeSegment        Destructor
  355.  
  356.  MemorySegment
  357.  : AbstractSegment, Block
  358.         MemorySegment(uShort)    Constructor
  359.         MemorySegment(uShort,    Constructor for specific descriptor
  360.             selector_t)
  361.         ~MemorySegment        Destructor-frees block and descriptor
  362.  
  363.  
  364.  
  365.  HugeMemorySegment
  366.  : HugeSegment, Block
  367.  
  368.  
  369.  The various memory classes provide structured access to DPMI's memory
  370.  management facilities.
  371.  
  372.  Note that of the classes defined, DOSMemory, MemorySegment, and 
  373.  HugeMemorySegment are unique in they that combine allocated memory and 
  374.  descriptors to address that memory.  The other classes are either
  375.  just memory (e.g. Block) or just descriptors (e.g. Segment, HugeSegment).
  376.  The distinctions between memory and descriptors are important to 
  377.  the conceptualization of the memory classes.
  378.  
  379.  *......................................................................
  380.  
  381.  The Block class corresponds to raw memory blocks allocated via DPMI
  382.  function 501h.     Defined operations on Blocks are limited to resize,
  383.  and free.  The class also supports query of the DPMI memory handle and
  384.  query of the block size. Blocks by themselves are not especially useful,
  385.  since the memory is not addressable.  Its purpose is to serve as a 
  386.  base class for MemorySegment and HugeMemorySegment.
  387.  
  388.  *......................................................................
  389.  
  390.  AbstractSegment is an abstract class the corresponds to a descriptor.
  391.  DPMI provides several means to create descriptors, all with slightly
  392.  different behavior. Although most members of AbstractSegment are pure,
  393.  a key member that it does implement is ptrTo, which returns a far
  394.  pointer that may be used to reference the linear address space that
  395.  the corresponding descriptor points to.
  396.  
  397.  *......................................................................
  398.  
  399.  The SegmentProperty enumeration provides an elegant means to add,
  400.  remove, and query properties of instances of derived classes of the
  401.  AbstractSegment class. It is defined as:
  402.  
  403.     typedef enum SegmentProperty
  404.     {
  405.         present,
  406.         executable,
  407.         readable,
  408.         writable,
  409.         big,
  410.         expandDown
  411.     } SegmentProp_t;
  412.  
  413.  The AbstractSegment class defines members operator+(SegmentProp_t) and
  414.  operator-(SegmentProp_t) that allow properties to be added and removed
  415.  with a natural syntax. For example, the code
  416.  
  417.     Segment mySeg();
  418.     mySeg - present;
  419.  
  420.  creates a descriptor and makes it not present.
  421.  
  422.  *......................................................................
  423.  
  424.  The Segment class corresponds to generic, fully modifiable LDT descriptors.
  425.  There are three DPMI services that create such descriptors, and thus
  426.  three constructors for the class. The first corresponds to DPMI function
  427.  0000, which allocates a descriptor.  The second corresponds to DPMI
  428.  function 000Dh, which allocates a specific descriptor.     The last
  429.  constructor corresponds to DPMI function 000Ah, which creates an alias
  430.  (same base and limit) to an existing segment.
  431.  
  432.  The default properties are present and writable. New Segments have a
  433.  base of zero and a size of one.
  434.  
  435.  The argument for the resize method is in bytes, and size==0
  436.  specifies a size of 64 KB.
  437.  
  438.  Specific descriptors must be in the range 04h to 0FFh.
  439.  
  440.  *......................................................................
  441.  
  442.  The CommonRealSegment class corresponds to descriptors created by DPMI
  443.  function 0002h, Convert Paragraph to Selector.     The intended use of 
  444.  this function is to provide addressability from protected mode for
  445.  commonly accessed regions of the low megabyte, such as the BIOS data
  446.  area (paragraph 40h) or the video display area (B800h etc.).
  447.  
  448.  DPMI restricts modification of descriptors created by function 0002h, and
  449.  therefore the resize, move, operator+(SegmentProp_t) and 
  450.  operator-(SegmentProp_t) members all return FALSE. Other members are 
  451.  inherited from AbstractSegment.
  452.  
  453.  *......................................................................
  454.  
  455.  The DOSMemory class corresponds to DPMI function 100h.     The constructor
  456.  uses this function to allocate a block of memory from DOS.  DPMI provides
  457.  a descriptor that allows addressability of the block from protected mode.
  458.  The argument to the constructor is the desired size in paragraphs of the
  459.  block.     If the allocation fails, the ptrTo function returns zero. The
  460.  paragraph address of the block is available via the segmentBase(void)
  461.  member inherited from AbstractSegment.     
  462.  
  463.  This code fragment:
  464.  
  465.     DOSMemory d(0x100);
  466.  
  467.     char far *p = (char far *)d.ptrTo();
  468.  
  469.  allocates 0x100 paragraphs of DOS memory and initializes a pointer to
  470.  it.  If the allocation fails, p is a null pointer.
  471.  
  472.  The resize member for DOSMemory maps to DPMI function 102h, Resize DOS
  473.  Memory Block; similarly, the destructor maps to function 101h, Free
  474.  DOS Memory Block. Because DPMI restricts any other modifications to these
  475.  blocks, the operator+(SegmentProp_t), operator-(SegmentProp_t), and move
  476.  members all return FALSE;
  477.  
  478.  *......................................................................
  479.  
  480.  A HugeSegment corresponds to a set of consecutive descriptors, which are
  481.  set up to span a address region of arbitrary size. The difference between
  482.  the base addresses of consecutive descriptors is 64 KB. The argument to 
  483.  the constructor is the size in bytes of the segment.
  484.  
  485.  For example, the code fragment
  486.  
  487.     HugeSegment  h(0x28000);
  488.     h.move(0x500000);
  489.  
  490.  results in the allocation of three descriptors having sizes of 0x10000,
  491.  0x10000, and 0x8000.  Calling the move member sets the base addresses
  492.  of the three descriptors to 0x500000, 0x510000, and 0x520000.
  493.  
  494.  Operations on a HugeSegment, such as adding or removing a property,
  495.  affect all of its component descriptors.  Likewise, the destructor
  496.  frees all the descriptors.
  497.  
  498.  HugeSegments cannot be grown if the new desired size requires additional
  499.  descriptors to span the region.  Shrinking a HugeSegment frees descriptors
  500.  no longer required to span it, and these cannot be reallocated to 
  501.  return the segment to its original size.
  502.  
  503.  *......................................................................
  504.  
  505.  A MemorySegment is a generic descriptor mapped to a block of DPMI memory.
  506.  The size is restricted by the argument to the constructor to be 64 KB 
  507.  or less.  Declaring a MemorySegment results in allocating both memory
  508.  and a descriptor initialized to address that memory.  
  509.  
  510.  The code fragment
  511.  
  512.         MemorySegment m(0x500);
  513.         short far *p = (short far *)m.ptrTo();
  514.  
  515.  makes p a far pointer to a 0x500 byte block of memory.     An zero argument
  516.  to the constructor requests a 64 KB block.
  517.  
  518.  An alternate constructor allows the MemorySegment to be allocated with
  519.  a specific descriptor.
  520.  
  521.  The resize and property members work as expected, but the move member 
  522.  returns FALSE since DPMI provides no means to move memory blocks.
  523.  
  524.  
  525.  *......................................................................
  526.  
  527.  A HugeMemorySegment is to a MemorySegment as a HugeSegment is to a
  528.  Segment.  A HugeMemorySegment is an arbitrarily large block of memory
  529.  with a set of consecutive descriptors that are set up to span it.  The
  530.  argument to the constructor is the size in bytes. As for MemorySegment,
  531.  the move member returns FALSE.
  532.  
  533.  
  534.  HugeMemorySegments cannot be grown if the new desired size requires 
  535.  additional descriptors to span the region.  Shrinking a HugeMemorySegment
  536.  frees descriptors no longer required to span it, and these cannot be 
  537.  reallocated to return the segment to its original size.
  538.  
  539.  *--------------------------------------------------------------------
  540.  
  541.  Header File: REALPROC.H  See example XREAL
  542.  
  543.  Classes    Members
  544.  -------    -------
  545.  RealProcedure
  546.         RealProcedure        Constructor.
  547.         operator()        Call operator invokes real
  548.                     mode procedure.
  549.         operator char()        char cast extracts char return
  550.                     value from real mode call structure.
  551.         operator int()        int cast extracts int return
  552.                     value from real mode call structure.
  553.         operator long()        long cast extracts long return
  554.                     value from real mode call structure.
  555.  
  556.  Applications occasionally require certain routines that cannot run in 
  557.  real mode, and must switch to real mode to execute them.  The RealProcedure
  558.  class corresponds to DPMI mechanisms for invoking (far) functions in 
  559.  real mode.
  560.  
  561.  The arguments for the constructor are the address of the real procedure
  562.  and the number of bytes of arguments the real procedure expects on the
  563.  stack when it is invoked.  The second argument is optional and defaults 
  564.  to zero.  The procedure address is near, and is assumed to be in the
  565.  default code segment.
  566.  
  567.  To invoke the RealProcedure, simply call it.  The class overrides the
  568.  call operator, and the member operator() makes the necessary DPMI calls
  569.  to run the registered routine in real mode.  The stack arguments, if any,
  570.  are copied to the stack on which the real mode routine is invoked.
  571.  
  572.  The class ensures that DS==SS when the real mode routine executes. Thus
  573.  the real mode routine can use any near pointers.
  574.  
  575.  An additional feature of the RealProcedure class is the ability to
  576.  return values.     Each class instance contains a dpmiRegs_t structure that
  577.  is used to pass the register state between modes. Upon return to protected
  578.  mode, this structure holds the register state in effect when the real
  579.  routine returned, and return values are contained therein.  To access
  580.  them, use the cast override members: operator char(), operator int() and
  581.  operator long().  Refer to the example code to see exactly how this is done.
  582.  *--------------------------------------------------------------------
  583.  
  584.  Header File: REALINT.H      See example XREAL
  585.  
  586.  Classes    Members
  587.  -------    -------
  588.  RealInterrupt
  589.         RealInterrupt        Constructor
  590.         operator()        Call operator invokes interrupt
  591.                     handler in real mode.
  592.  
  593.  A RealInterrupt corresponds to the DPMI function that switches to 
  594.  real mode and issues a particular interrupt after installing a
  595.  register state supplied by the caller.     Unlike the RealProcedure class,
  596.  the interface to RealInterrupt assumes register-based argument passing.
  597.  
  598.  The argument to the constructor is the number of the interrupt, from
  599.  zero to 255.  The member operator() (call override operator) is used
  600.  to invoke the real mode interrupt.  This requires a dpmiRegs_t 
  601.  structure as an argument.  Upon return from the interrupt, the dpmiRegs_t 
  602.  structure reflects the register state at the time the real mode
  603.  interrupt handler returned.
  604.  
  605.  The caller is required to set up the dpmiRegs_t structure that is passed
  606.  when the real interrupt is called.  This includes setting up the stack
  607.  (SS:SP fields) and the flags.    Setting SS and SP requests the DPMI host
  608.  to provide a stack.  The flags value should be chosen carefully, 
  609.  especially with regard to the Interrupt Enable bit and the Trace bit.
  610.  
  611.  An example of using a RealInterrupt is included in the TestCallBack function
  612.  of the XREAL.CPP example.
  613.  
  614.  *--------------------------------------------------------------------
  615.  
  616.  
  617.  Header File: CALLBACK.H  See example XREAL
  618.  
  619.  Classes    Members
  620.  -------    -------
  621.  CallBack    CallBack        Constructor; allocates real mode 
  622.                     call-back and initialize register
  623.                     structure; saves callback address
  624.         ~CallBack        Destructor; releases call back.
  625.         getCallBackAddress    Returns the call back address.
  626.  
  627.  DPMI provides a mechanism for call protected mode routines from real
  628.  mode.    Unfortunately, the mechanism is rather complex.     The CallBack
  629.  class goes a long way in simplifying the task of using real mode
  630.  call backs.
  631.  
  632.  The single arguemnt to the constructor is the address of the call back
  633.  handler.  The call back handler is a routine that called from real mode
  634.  but runs in protected mode.  The class includes dispatching logic that
  635.  allows you to code the handler as a normal near routine, and allows you to
  636.  assume that DS==SS.  The argument to the handler is a dpmiRegs_t
  637.  structure that reflects the interrupt state at the time of the call.
  638.  Any changes the handler makes to this structure are reflected in the
  639.  register state when the handler returns to real mode.
  640.  
  641.  
  642.  The handler should only be invoked by calling to the far callback address
  643.  from real mode.  The callback address is obtained with the getCallBackAddress
  644.  member.  See function TestCallBack in the XREAL example.
  645.  
  646.  *......................................................................
  647.  
  648.  Header File: DPMIINT.H     See examples XINTR, XREAL
  649.  
  650.  Classes    Members
  651.  -------    -------
  652.  InterruptHandler
  653.         InterruptHandler    Constructor; hooks interrupt.
  654.         ~InterruptHandler    Destructor; unhooks interrupt.
  655.         callPrevious        Invokes previous handler.
  656.  
  657.  RealInterruptHandler
  658.  : InterruptHandler
  659.         RealInterruptHandler    Constructor; hooks real interrupt.
  660.         ~RealInterruptHandler    Destructor; unhooks real interrupt.
  661.  
  662.  
  663.  The interrupt handling classes make it very easy to create handlers for
  664.  hardware and software interrupts, both in real mode and protected mode.
  665.  The class handles all the necessary interaction with DPMI for saving the
  666.  previous vector, and for setting the interrupt vector to the user's handler.
  667.  
  668.  The class further simplifies creation of handlers by allowing the user
  669.  to code the handler as a normal function, i.e, the user does not need to
  670.  declare it as _interrupt, and may assume that DS==SS, which is important
  671.  in small model programs.  This is accomplished by the interrupt dispatching
  672.  logic built into the class (see Implementation Notes for more information).
  673.  
  674.  The arguments to the constructor are the interrupt number and the address
  675.  of the routine that the user assigns to handle the interrupt. The argument
  676.  to the user's handler routine is a dpmiRegs_t structure, which reflects
  677.  the register state at the time the interrupt occurs.  Changes to the
  678.  dpmiRegs_t argument made by the handler are reflected as changes to the 
  679.  register state when the handler returns.  For example, a software interrupt 
  680.  handler that returns a value in AX modifies the drAX field of the dpmiRegs_t
  681.  argument. Likewise, a hardware interrupt handler which preserves the 
  682.  register state must make no changes to the dpmiRegs_t argument.
  683.  
  684.  The member callPrevious is useful for calling the handler that was in
  685.  effect when the user handler was created.  The argument to callPrevious
  686.  is a pointer to the dpmiRegs_t structure, which is necessary in order 
  687.  to present the correct register state to the previous handler.     Any changes
  688.  made to the register state by the previous handler are reflected in the
  689.  dpmiRegs_t structure upon return. RealInterruptHandlers inherit this member.
  690.  
  691.  The destructors restore the previous vector.
  692.  
  693.  *--------------------------------------------------------------------
  694.  
  695.  Header file: EXCEPTIO.H  See example XCEPT
  696.  
  697.  Classes    Members
  698.  -------    -------
  699.  ExceptionHandler
  700.         ExceptionHandler    Constructor. Hooks exception.
  701.         ~ExceptionHandler    Destructor. Restores vector
  702.         callPrevious        Invokes previous handler.
  703.  
  704.  The ExceptionHandler class makes it easy to create handlers for 
  705.  processor exceptions, such as General Protection violation, Segment
  706.  Not Present, etc.  As with InterruptHandlers, the class provides
  707.  dispatching such that handlers run with DS==SS, so that all near pointers
  708.  are valid, and handlers are declared as normal near functions.
  709.  
  710.  The arguments to the constructor are the exception number to handle,
  711.  and the address of the handler.  The class takes care of calling DPMI
  712.  to get the previous vector and set up for the new handler.
  713.  
  714.  When the handler is invoked, there are two structures passed to it. The
  715.  first is a dpmiRegs_t structure which reflects the register state at 
  716.  the time the exception occurred.  The second is the DPMI exception
  717.  frame, which gives the CS:IP, SS:SP, and flags at the time of the 
  718.  exception.  The handler may modify fields in the register structure
  719.  and/or the exception frame structure, and such changes are observed 
  720.  by the host when the handler returns.
  721.  
  722.  The member callPrevious is used to invoke the previous handler for the
  723.  exception.  It is passed pointers to the register state and to the 
  724.  exception frame, which it may modify.
  725.