home *** CD-ROM | disk | FTP | other *** search
/ Der Mediaplex Sampler - Die 6 von Plex / 6_v_plex.zip / 6_v_plex / DISK5 / DOS_42 / XLIB30.ZIP / XLIB.DOC < prev    next >
Text File  |  1993-12-20  |  129KB  |  3,240 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.                              XLIB PROGRAMMER'S MANUAL
  31.                                    VERSION 3.0
  32.  
  33.                               (DOS Extender Library)
  34.  
  35.                                 TechniLib Company
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.                     Copyright 1993, by TechniLib (TM) Company
  60.                                All Rights Reserved
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.                           TERMS OF USE AND DISTRIBUTION
  68.  
  69.  
  70.        XLIB is a shareware product; therefore, unregistered copies of XLIB are
  71.   made available free of charge so that potential purchasers will have the
  72.   opportunity to examine and test the software before committing payment.
  73.   Distribution of unregistered copies of XLIB to other potential users is also
  74.   permitted and appreciated.  However, usage and distribution of XLIB must
  75.   conform to the following conditions.  In the following statement, the term
  76.   "commercial distribution," includes shareware distribution.
  77.  
  78.   1) XLIB and accompanying software must be distributed together in copies of
  79.   the original archive provided by TechniLib.  Neither the archive nor
  80.   individual files therein may be modified.
  81.  
  82.   2) The XLIB archive may be distributed in combination with other shareware
  83.   products; however, the XLIB archive may not be distributed with other
  84.   commercially distributed software without written consent of TechniLib.
  85.  
  86.   3) Copies of XLIB which have been used to develop software for commercial
  87.   distribution must be registered before such software is marketed.  Copies of
  88.   XLIB which have been used to develop noncommercial software must be registered
  89.   if such software is to be regularly used either by the developer or others.
  90.  
  91.   4) Commercially distributed software must embed XLIB procedures in the
  92.   software code.  Files contained in the XLIB archive may not be placed in the
  93.   distribution media.
  94.  
  95.   5) XLIB is designed to offer a set of services to other executable code.  XLIB
  96.   may not be used to develop software for commercial distribution which will
  97.   essentially offer any of these same services to other executable code.
  98.   Exceptions to this condition require written consent of TechniLib.
  99.  
  100.   6) Rights afforded by registering a single copy of XLIB pertain only to a
  101.   single computer.
  102.  
  103.   7) XLIB may be registered for a fee of $40.00 per copy.  Accompany payment
  104.   with the registration form included in the XLIB archive.  Registrants will be
  105.   entitled to the most recent version of the XLIB archive.
  106.  
  107.  
  108.                               DISCLAIMER OF WARRANTY
  109.  
  110.  
  111.        XLIB AND ALL ACCOMPANYING SOFTWARE AND LITERATURE ARE DISTRIBUTED WITH
  112.   THE EXCLUSION OF ANY AND ALL IMPLIED WARRANTIES, AND WITH THE EXCLUSION OF
  113.   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  TechniLib
  114.   SHALL HAVE NO LIABILITY FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  115.   RESULTING FROM THE USE OF XLIB OR ACCOMPANYING MATERIALS.  The user assumes
  116.   the entire risk of using this software.
  117.  
  118.  
  119.                     Copyright 1993, by TechniLib (TM) Company
  120.                                All Rights Reserved
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.                                 TABLE OF CONTENTS
  128.  
  129.  
  130.   CHAPTERS
  131.                                                                       Page
  132.   1.  Introduction                                                       1
  133.   2.  XLIB Conventions and Structure                                     4
  134.   3.  XLIB Initialization and Termination                                7
  135.   4.  Mode Switching                                                    10
  136.   5.  Inline Mode Switching                                             14
  137.   6.  Interrupt Management                                              18
  138.   7.  Memory Management                                                 24
  139.   8.  File Management                                                   28
  140.   9.  Descriptor Management                                             33
  141.   10. Using XLIB in High-Level Language Libraries                       34
  142.  
  143.  
  144.   TABLES
  145.                                                                       Page
  146.   1.  XLIB Segments and Selectors by Public Symbol                       5
  147.   2.  IFLAGS Settings for Memory Allocation Control                      8
  148.   3.  CALLPM/ENTERPM Register Storage Locations by Public Symbol        12
  149.   4.  CALLRM Register Storage Locations by Public Symbol                13
  150.   5.  XLIB File Control Block Structure                                 28
  151.  
  152.  
  153.   EXAMPLES
  154.                                                                       Page
  155.   1.  Simple Mode Switching Under XLIB                                   3
  156.   2.  Using INLINEPM/INLINERM in C                                      15
  157.   3.  Calling Protected-Mode Libraries From BASIC                       34
  158.  
  159.  
  160.   APPENDICES
  161.                                                                       Page
  162.   A. Description of XLIB Public Data                                    38
  163.   B. XLIB Error Codes                                                   41
  164.   C. DPMI 1.0 Error Codes                                               43
  165.   D. XMS Error Codes                                                    44
  166.   E. Calling Protected-Mode Libraries From C                            45
  167.   F. Reporting Problems With XLIB                                       47
  168.   G. The SWITCHPM and SWITCHRM Procedures                               48
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.                                  1. Introduction
  176.  
  177.  
  178.        XLIB is an assembly language library which greatly simplifies protected-
  179.   mode programming under the Microsoft DOS operating system.  Assembly language
  180.   programmers will likely abandon real-mode programming after acquiring XLIB.
  181.   With only two calls to XLIB procedures, assembly language programs can be
  182.   utilizing the simplicity and power of 32-bit processing.  C and C++ programs
  183.   can harness the powers of 16-bit protected mode using inline assembly.
  184.   Additionally, the XLIB archive contains a second library call EASYX which can
  185.   be used by all high-level languages to gain access to extended memory.
  186.        XLIB is designed for the Intel 386, 486, and Pentium processors.  XLIB
  187.   fully utilizes the 32-bit processing powers of these chips and makes these
  188.   powers available to the user.  The compactness of XLIB follows largely from
  189.   the fact that much of it is written in 32-bit code.
  190.        Previous versions of XLIB contained only Microsoft compatible files;
  191.   however, the archive for XLIB version 3.0 includes libraries and sample code
  192.   in both Microsoft and Borland formats.
  193.        XLIB is used to produce extended DOS applications.  DOS is unfortunately
  194.   limited by the fact that it is a real-mode operating system intended to manage
  195.   only real-mode programs.  Real-mode programs cannot use memory addresses
  196.   requiring more than 20 bits, or use memory offsets requiring more than 16
  197.   bits.  Such programs are further limited by the fact that 32-bit instructions
  198.   execute awkwardly in real-mode.  When the processor is in real-mode, it will
  199.   expect all 32-bit instructions to be preceded by at least one prefix.  Each of
  200.   these prefixes consumes one byte of memory and requires at least one clock to
  201.   execute.  Such limitations do not exist in 32-bit protected mode.  Extended
  202.   DOS applications overcome the limitations of DOS with their ability to execute
  203.   in both real and protected modes.  DOS services can be utilized from real mode
  204.   while the 32-bit processing power of the CPU can be utilized from protected
  205.   mode.
  206.        There are presently several 32-bit operating systems available on the
  207.   market.  Such systems include IBM OS/2, Microsoft Windows NT, and UNIX.  These
  208.   systems can manage programs which operate exclusively in protected mode.  Such
  209.   programs are generally easier to develop than extended DOS applications.
  210.   However, extended DOS applications have an advantage in that they can execute
  211.   under all of these operating systems because all of these systems can emulate
  212.   DOS.
  213.        Of course DOS will eventually become obsolete.  Future programs will
  214.   likely operate exclusively in protected mode using the flat (unsegmented)
  215.   memory model.  The memory models supported by XLIB approximate the flat model;
  216.   therefore, code written for XLIB will require little modification when being
  217.   transported to flat-model operating environments.  Indeed, many procedures
  218.   will require no modification whatsoever.  Moreover, XLIB includes flat-model
  219.   descriptors which may be used to execute genuine flat-model code.  XLIB does
  220.   not load and relocate such code; however, it does provide all the necessary
  221.   tools to develop such procedures.
  222.        XLIB procedures handle important tasks such as mode switching between
  223.   real and protected modes, memory management under protected mode, protected-
  224.   mode interrupt management, and protected-mode file management.  XLIB includes
  225.   routines to perform these tasks in the absence of a protected-mode interface,
  226.   or in the presence of the Virtual Control Program Interface (VCPI), or the DOS
  227.   Protected Mode Interface (DPMI, version .9 or higher).  XLIB can also manage
  228.   extended memory through the Extended Memory Specification (XMS).  This
  229.  
  230.  
  231.  
  232.                                         1
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.   versatility makes XLIB compatible with nearly all common operating
  240.   environments for 386, 486, and Pentium processors.
  241.        Upon initialization, XLIB will examine the operating environment for the
  242.   presence of DPMI, VCPI, and XMS, and then configure itself accordingly.  The
  243.   client program may therefore perform calls to XLIB procedures with few
  244.   concerns as to the environment in which it is executing.
  245.        This manual is not intended to teach protected-mode programming.  It is
  246.   assumed that the reader has a general knowledge of protected mode and a
  247.   working knowledge of assembly language.  Programmers who are unfamiliar with
  248.   assembly language and who need protected-mode execution merely to access
  249.   extended memory from within high-level languages should consider using the
  250.   EASYX library.  This library is a real-mode interface to XLIB.  It contains
  251.   procedures which may be utilized without assembly language.  The documentation
  252.   for EASYX is included in the XLIB archive.  The reader might wish to refer to
  253.   this documentation now; however, the present document may still be needed for
  254.   technical reference.
  255.        XLIB relieves the programmer of descriptor table management by supplying
  256.   a set of predefined segments along with their associated descriptors and
  257.   selectors.  Many protected-mode procedures will require no modification for
  258.   XLIB other than being placed in the proper segment.  XLIB provides a single
  259.   32-bit segment for protected-mode routines.  This segment may be larger than
  260.   64K, but must reside in conventional memory so that DOS can load it.  However,
  261.   code within this segment may access data throughout the address space.  XLIB
  262.   does allow user-defined descriptors; however, these should be needful only in
  263.   very rare cases.
  264.        The following program illustrates the simplicity with which protected-
  265.   mode execution may be initiated and terminated with XLIB.  The program was
  266.   written with the Microsoft Assembler (MASM).  It first initializes XLIB by
  267.   calling a procedure called INITXLIB.  After confirming that initialization is
  268.   successful, the program then transfers control to a 32-bit protected-mode
  269.   procedure which prints a message to the screen.  Control is transferred by
  270.   placing the protected-mode target address on the stack and then calling an
  271.   XLIB procedure named CALLPM (call protected mode).  CALLPM will expect the
  272.   target procedure to be contained in a segment called TSEG.  The protected-mode
  273.   procedure in TSEG returns control to real or virtual 8086 (V86) mode simply by
  274.   executing the RET instruction.
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.                                         2
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.   Example 1:  Simple Mode Switching Under XLIB
  304.   _____________________________________________________________________________
  305.                  .MODEL        LARGE,PASCAL
  306.                  .386P
  307.  
  308.                  INCLUDE        XLIB.INC       ;Include XLIB public symbols
  309.                  INCLUDELIB     XLIB.LIB       ;Link with XLIB.LIB
  310.  
  311.                  .STACK         1024
  312.                  .CODE
  313.                  .STARTUP
  314.  
  315.                  CALL           INITXLIB       ;Initialize XLIB
  316.                  OR             EAX,EAX        ;EAX = 0 if successful
  317.                  JZ             INITDONE
  318.                  .EXIT          0              ;Initialization failed
  319.  
  320.   INITDONE:      PUSHD          OFFSET DEMOPROC
  321.                  CALL           CALLPM         ;Execute DEMOPROC in protected
  322.                  .EXIT          0
  323.  
  324.   ;Protected-mode routines must be placed in following segment:
  325.   TSEG           SEGMENT PARA PUBLIC USE32 'CODE'
  326.                  ASSUME CS:TSEG, SS:TSEG, DS:TSEG, ES:TSEG, FS:DSEG, GS:DGROUP
  327.  
  328.   ;Protected-mode routine to print message to the screen using DOS function.
  329.   DEMOPROC       PROC NEAR
  330.                  MOV            EBX,OFFSET PMMSG
  331.                  MOV            AH,02H
  332.   MSGLOOP:       MOV            DL,CS:[EBX]    ;32-bit offset!!!!!
  333.                  OR             DL,DL
  334.                  JZ             EXIT
  335.                  INT            21H            ;Print character with DOS
  336.                  INC            EBX
  337.                  JMP            MSGLOOP
  338.   EXIT:          RET                           ;Go back to real or V86 mode
  339.   PMMSG          DB  "In 32-bit protected mode!!!  "
  340.                  DB  "Returning to real mode.",10,13,0
  341.   DEMOPROC       ENDP
  342.  
  343.   TSEG           ENDS
  344.                  END
  345.   _____________________________________________________________________________
  346.  
  347.  
  348.        The framework presented in the above program is extremely simple;
  349.   nonetheless, it will meet the demands of many protected-mode programs.  Most
  350.   protected-mode programs will require no further complications apart from a few
  351.   calls to XLIB extended memory management procedures.
  352.        To achieve the simplicity of the above program, XLIB must handle numerous
  353.   complexities internally.  This manual attempts to give the reader thorough
  354.   insight into the workings of XLIB.  It also discusses at length the numerous
  355.   configuration options that are available to the programmer.
  356.  
  357.  
  358.  
  359.  
  360.                                         3
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.                         2. XLIB Conventions and Structure
  368.  
  369.  
  370.        The XLIB archive contains files for both Microsoft and Borland languages.
  371.   The files for Borland have the same names as those for Microsoft except a "B"
  372.   is added to the base name.  For example, XLIB.LIB is the XLIB library intended
  373.   for Microsoft languages whereas XLIBB.LIB is intended for Borland languages.
  374.   Sample code in this document is always for Microsoft languages; however,
  375.   Borland versions may be found in the archive.  Important information about
  376.   using XLIB with Microsoft and Borland languages has been included in the
  377.   README.DOC file.
  378.        The Microsoft version of XLIB was developed and tested under Microsoft
  379.   DOS version 6.0 using Microsoft Assembler (MASM) version 6.11, Microsoft LINK
  380.   version 5.31.009, and Microsoft LIB version 3.20.01.  The Borland version of
  381.   XLIB was developed and tested using Turbo Assembler (TASM) version 3.1, TLINK
  382.   version 5.0, and TLIB version 3.02.
  383.        XLIB has been tested under Microsoft Windows 3.1, Qualitas 386MAX version
  384.   6.02, Quarterdeck QEMM versions 6.02 and 7.03, Quarterdeck QDPMI versions 1.01
  385.   and 1.03, Quarterdeck DESQview version 2.42, and IBM OS/2 version 2.1.
  386.        XLIB public procedures and public data are explained in the following
  387.   chapters.  A detailed explanation of most XLIB public data is also included in
  388.   Appendix A.  This chapter sets forth rules which will be generally applicable
  389.   to all XLIB data and procedures.
  390.        Though it is sometimes necessary for XLIB to distinguish between real
  391.   mode and virtual 8086 mode; this document uses the term "real mode" to include
  392.   virtual 8086 mode.
  393.        All public real-mode procedures and 16-bit protected-mode procedures in
  394.   XLIB are located in a segment called CSEG.  The user may also place code in
  395.   CSEG but is rarely required to do so.  All public XLIB procedures in CSEG have
  396.   far returns.
  397.        All public 32-bit protected-mode procedures in XLIB are located in a 32-
  398.   bit segment called TSEG and have near returns.  XLIB will also expect the user
  399.   to place all 32-bit procedures in TSEG and will expect these procedures to
  400.   have near returns.  This policy is adopted to achieve approximation to the
  401.   flat model.
  402.        Nearly all XLIB protected-mode procedures are 32-bit routines.  The only
  403.   exceptions to this rule are the inline mode-switch procedures discussed in
  404.   Chapter 5.  This policy is implemented to approximate the flat model.  There
  405.   are very few circumstances in which 16-bit protected mode is preferable to 32-
  406.   bit protected mode.  One can generally increase program speed and reduce
  407.   program size by writing the code for 32-bit segments.
  408.        TSEG may be larger than 64K provided that certain rules are observed.
  409.   XLIB adheres to all of the necessary rules.  First, only 32-bit protected-mode
  410.   code should be placed in TSEG.  The processor will not generally be able to
  411.   execute real-mode code in this segment because the offsets will be 32-bit
  412.   values.  Second, real-mode code should never write to or read from TSEG.  Such
  413.   instructions will also require 32-bit offsets.  Modifications to TSEG should
  414.   be done from a TSEG protected-mode procedure.  Finally, segment constants
  415.   should never be encoded in TSEG.  For example, the symbols CSEG, TSEG, DSEG,
  416.   and DGROUP should not be found in TSEG.  DOS will not be able to perform
  417.   relocation edits on these constants if they are in a segment larger than 64K.
  418.   To read these values from TSEG, initialize memory locations in a 16-bit
  419.   segment to the values and then read the memory locations.  Memory locations in
  420.   DSEG have already been initialized for XLIB segments (see Appendix A).
  421.  
  422.  
  423.  
  424.                                         4
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.   Microsoft LINK will issue a warning for code segments exceeding 64K; however,
  432.   this warning may be safely ignored provided that the above rules are observed.
  433.        All XLIB procedures may be called with interrupts enabled and will return
  434.   with interrupts enabled provided that they were enabled upon call.
  435.        With one exception, all XLIB public data is contained in a 16-bit segment
  436.   called DSEG.  The user may also place data in DSEG but is rarely required to
  437.   do so.
  438.        XLIB uses the PASCAL calling and naming convention.  The PASCAL
  439.   convention is equivalent to the BASIC and FORTRAN conventions.  C programmers
  440.   must adapt XLIB procedures and symbols with declarations which specify the
  441.   PASCAL convention.  The header file XLIB.H contains such declarations.
  442.        XLIB routines which can encounter error conditions will always return
  443.   XLIB error codes in AX.  A list of such error codes is presented in Appendix
  444.   B.  In most cases, DX or the high word of EAX will be returned with specific
  445.   information about the error, such as DPMI, XMS, or DOS error codes.  DPMI
  446.   error codes are presented in Appendix C.  XMS error codes are in Appendix D.
  447.        Selectors for all XLIB segments are placed in public WORD locations in
  448.   segment DSEG.  The following table gives the name of each predefined selector
  449.   along with its associated segment name and description:
  450.  
  451.  
  452.   Table 1:  XLIB Segments and Selectors by Public Symbol
  453.   _____________________________________________________________________________
  454.   Selector Name    Segment Name      Description
  455.   -------------    ------------      -----------
  456.   CSEGSEL          CSEG              XLIB 16-bit code segment
  457.   CSEGDSEL         CSEG              Data selector to CSEG
  458.   TSEGSEL          TSEG              32-bit code segment
  459.   TSEGDSEL         TSEG              Data selector to TSEG
  460.   DSEGSEL          DSEG              XLIB data segment
  461.   FLATSEL          .                 Flat-model code
  462.   FLATDSEL         .                 Flat-model data
  463.   DGROUPSEL        DGROUP            DGROUP data group
  464.   SCRNSEL          .                 Screen data
  465.   MAINCSSEL        .                 CS selector for main caller
  466.   MAINSSSEL        .                 SS selector for main caller
  467.   MAINDSSEL        .                 DS selector for main caller
  468.   MAINESSEL        .                 ES selector for main caller
  469.   ILCSSEL          .                 Inline CS selector
  470.   ILSSSEL          .                 Inline SS selector
  471.   ILDSSEL          .                 Inline DS selector
  472.   _____________________________________________________________________________
  473.  
  474.  
  475.        The flat-model and TSEG descriptors have limit FFFFFFFFH.  All other
  476.   descriptors have limit FFFFH.  The screen descriptor has base set to B8000H
  477.   for color monitors and B0000H for monochrome monitors.  MAINCSSEL, MAINSSEL,
  478.   MAINDSSEL, and MAINESSEL are selectors to descriptors which have base
  479.   addresses matching the contents of CS, SS, DS, and ES as of the call to
  480.   INITXLIB.  ILCSSEL, ILSSSEL, and ILDSSEL are selectors used by the inline
  481.   mode-switch procedures (see Chapter 5).  The base addresses of the
  482.   corresponding descriptors are adjusted dynamically.
  483.        All data segments are writable.  The data descriptors have their big bits
  484.   set; consequently, implicit stack instructions will use ESP rather then SP.
  485.  
  486.  
  487.  
  488.                                         5
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.   All code segments are readable and nonconforming.  Descriptor privilege levels
  496.   and requested privilege levels are set to zero unless DPMI is installed.
  497.   Privilege levels under DPMI will generally be set to three.
  498.        The values contained in the above selectors will be different under DPMI
  499.   than other environments.  Moreover, DPMI selector values can differ in
  500.   different environments and under different hosts.  Therefore, the user should
  501.   not assume these values to be constant.
  502.        Since selector values are stored in DSEG, the user must never lose track
  503.   of the DSEG selector.  This could prove a problem in interrupt handlers where
  504.   no assumptions can be made as to register contents.  Consequently, XLIB places
  505.   a copy of the DSEG selector in TSEG where it can always be found.  It is
  506.   stored under WORD symbol CSDSEGSEL and may be read with CS override.  For
  507.   example from TSEG code you can always load DS with DSEGSEL using MOV
  508.   DS,CS:CSDSEGSEL.
  509.        XLIB never uses selectors past DGROUPSEL in Table 1.  The user may
  510.   therefore redefine the associated descriptors if desired (see Chapter 9).
  511.   Selector values however should not be changed.
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.                                         6
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.                       3. XLIB Initialization and Termination
  560.  
  561.  
  562.        XLIB procedures apart from those presented in this chapter should be
  563.   called only after XLIB has been initialized by calling INITXLIB.  This routine
  564.   will examine the operating environment for the presence of DPMI, VCPI, and
  565.   XMS.  It will then perform extensive code modifications upon XLIB to
  566.   accommodate the resident software.  INITXLIB is to be called only once within
  567.   a program.  Subsequent calls have no effect.
  568.        If XLIB finds that neither DPMI nor VCPI are present, then XLIB will
  569.   completely handle all mode switching and interrupt management.  If XLIB finds
  570.   that XMS is absent also, then XLIB will handle all extended memory management.
  571.   If XLIB finds that both DPMI and VCPI are present, then it will configure
  572.   itself for DPMI by default.  However, the default may be changed by setting
  573.   bit 0 of IFLAGS (initialization flags) before calling INITXLIB.  If this bit
  574.   is set, then VCPI is given priority over DPMI.  IFLAGS is a public WORD
  575.   location in DSEG.
  576.        INITXLIB will possibly attempt to allocate some memory through DOS.
  577.   Since high-level language modules and assembly language modules often claim
  578.   all available conventional memory, INITXLIB may fail for lack of available
  579.   memory.  This problem can be averted with MASM programs by linking with the
  580.   CPARM:1 parameter.  This forces the program to claim no more conventional
  581.   memory than is necessary.  TASM programs and some high-level language programs
  582.   should release memory to DOS during initialization.  This process is
  583.   illustrated for TASM in the file EXAMP1B.ASM.  In some cases, the main program
  584.   will need to retain all memory except what is necessary for XLIB.  The XLIB
  585.   procedure XLIBMEMREQ (XLIB memory requirements) may be called to obtain
  586.   conventional memory requirements for XLIB.  Usage of XLIBMEMREQ is illustrated
  587.   for Microsoft BASIC in Chapter 10.  C and C++ do not allocate all conventional
  588.   memory and therefore do not require any special action.
  589.        If both VCPI and DPMI are present, then conventional memory requirements
  590.   will depend upon which of these interfaces is to be chosen by INITXLIB.  In
  591.   such cases, XLIBMEMREQ will return DPMI memory requirements if bit 0 of IFLAGS
  592.   is clear (the default), and will return VCPI requirements otherwise.
  593.   Therefore, this bit should be set to the appropriate value by the user before
  594.   calling XLIBMEMREQ.  DPMI conventional memory requirements may be obtained by
  595.   calling DPMIMEMREQ.  These will vary from host to host.  VCPI conventional
  596.   memory requirements may be obtained by calling VCPIMEMREQ.  VCPI requirements
  597.   are slightly over 12K and are the same for all servers.
  598.        One of the principle function of XLIB is of course to make protected-mode
  599.   interfaces and memory management interfaces transparent to the client program.
  600.   However, there are special cases where a program should be informed as to
  601.   which interfaces are implemented.  In such cases, the procedure XLIBCONFIG
  602.   (XLIB configuration) may be called to determine the how XLIB has been
  603.   configured by INITXLIB.
  604.        XLIB is terminated with INT 21H function 4CH (DOS termination) issued
  605.   either from real or protected mode.
  606.  
  607.  
  608.  
  609.  
  610.  
  611.  
  612.  
  613.  
  614.  
  615.  
  616.                                         7
  617.  
  618.  
  619.  
  620.  
  621.  
  622.  
  623.   Detailed Specifications
  624.  
  625.  
  626.   INITXLIB (Initialize XLIB)
  627.   Purpose:  Check for presence of XMS, DPMI, and VCPI, then configure XLIB to
  628.   operate with the installed interfaces.
  629.   CPU Mode:  Real
  630.   Registers at Call:  None
  631.   Return Registers:
  632.      AX = 0 if successful, in which event DX and EAX are zero as well.  The
  633.   configured interfaces may be identified by calling XLIBCONFIG (see below).
  634.      AX <> 0 if unsuccessful.  An XLIB error code is returned in AX.  A specific
  635.   error code is returned in DX and in the high word of EAX (EAH).  If AX = 11H
  636.   or 12H, then DX and EAH will equal a DOS error code.  If AX = DPMI error, then
  637.   DX and EAH will equal a DPMI 1.0 error code (if provided by host).  If AX =
  638.   VCPI error, then DX and EAH are returned as zero.
  639.   Details:
  640.      If both DPMI and VCPI are present, then XLIB will be configured for DPMI if
  641.   the zero bit of IFLAGS is clear.  If this bit is set, then XLIB will be
  642.   configured for VCPI.  The bit is clear by default.
  643.      This routine will possibly attempt to allocate conventional memory.  The
  644.   amount of memory XLIB will attempt to allocate can be obtained by calling
  645.   XLIBMEMREQ (see below).  The general address range from which this memory is
  646.   allocated can be controlled by appropriately setting the high byte of IFLAGS.
  647.   Alternative values for this byte are presented in Table 2.  The byte has a
  648.   value of 2 by default.  This setting forces XLIB to allocate from the highest
  649.   available address in conventional memory.  Under certain settings of IFLAGS,
  650.   XLIB can also allocate from upper memory (DOS 5.0 or higher).
  651.      Descriptors are created for the segments loaded in CS, SS, DS, and ES as of
  652.   call to this routine.  The selectors for these descriptors are MAINCSSEL,
  653.   MAINSSSEL, MAINDSSEL, and MAINESSEL.  These descriptors are never used by
  654.   other XLIB procedures.  They are provided to augment development of protected-
  655.   mode libraries.  Protected-mode library routines may access the stack and data
  656.   of the main program through these descriptors.
  657.      INITXLIB should be called only once within a program.  Subsequent calls are
  658.   returned with no action.  XLIB is terminated by INT 21H function 4CH (DOS
  659.   termination) issued from either real or protected mode.
  660.  
  661.  
  662.   Table 2:  IFLAGS Settings for Memory Allocation Control
  663.   _____________________________________________________________________________
  664.   Bits 8-15     Implied Memory Allocation Location
  665.   ---------     ----------------------------------
  666.   00H           Lowest available address in conventional memory (00000H-9FFFFH)
  667.   01H           Best fit in conventional memory
  668.   02H           Highest available address in conventional memory
  669.   40H           Lowest available address in upper memory (A0000H-FFFFFH)
  670.   41H           Best fit in upper memory
  671.   42H           Highest available address in upper memory
  672.   81H           Follow strategy 40H by 00H if necessary
  673.   82H           Follow strategy 41H by 01H if necessary
  674.   83H           Follow strategy 42H by 02H if necessary
  675.   _____________________________________________________________________________
  676.  
  677.  
  678.  
  679.  
  680.                                         8
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.   XLIBMEMREQ (XLIB Memory Requirements)
  688.   Purpose:  Find XLIB conventional memory requirements.
  689.   CPU Mode:  Real
  690.   Registers at Call:  None
  691.   Return Registers:
  692.      Sign bit of DX clear if successful.  Memory requirements in bytes are
  693.   returned in DX:AX.
  694.      Sign bit of DX set if unsuccessful.  An error code is returned in AX
  695.   (always a DOS error code).
  696.   Details:
  697.      DX:AX is adjusted upward to an integer multiple of 16.
  698.      If both DPMI and VCPI are present, then XLIBMEMREQ will assume that DPMI
  699.   will be used if bit 0 of IFLAGS is clear (the default); otherwise, VCPI is
  700.   assumed.  No additional conventional memory is needed if both DPMI and VCPI
  701.   are absent.
  702.      This routine will return DX:AX = 0 if XLIB contains free internal memory in
  703.   sufficient quantity to meet conventional memory demands.
  704.      This routine obtains DPMI requirements by calling DPMIMEMREQ (see below)
  705.   and VCPI requirements by calling VCPIMEMREQ.
  706.  
  707.   DPMIMEMREQ  (DPMI Memory Requirements)
  708.   Purpose:  Find DPMI conventional memory requirements.
  709.   CPU Mode:  Real
  710.   Registers at Call:  None
  711.   Return Registers:  DX:AX = conventional memory requirements.
  712.   Details:
  713.      DX:AX is adjusted upward to an integer multiple of 16.
  714.      This routine does not assume the presence of DPMI.  It will return DX:AX
  715.   set to zero if DPMI is absent.
  716.      This routine will return DX:AX = 0 if XLIB contains free internal memory in
  717.   sufficient quantity to meet the conventional memory demands of DPMI.
  718.  
  719.   VCPIMEMREQ (VCPI Memory Requirements)
  720.   Purpose:  Find VCPI conventional memory requirements.
  721.   CPU Mode:  Real
  722.   Registers at Call:  None
  723.   Return Registers:  DX:AX = conventional memory requirements.
  724.   Details:
  725.      DX:AX is adjusted upward to an integer multiple of 16.
  726.      This routine simply loads DX:AX with a constant slightly greater than 12Kb.
  727.  
  728.   XLIBCONFIG (XLIB Configuration)
  729.   Purpose:  Get XLIB configuration.
  730.   CPU Mode:  Real
  731.   Registers at Call:  None
  732.   Return Registers:  AX = 0 if protected-mode structures are not initialized;
  733.   otherwise, AX = XLIB configuration.  The value of lower nibble identifies the
  734.   protected-mode host/server.  If 1 then DPMI is installed.  If 2 then VCPI is
  735.   installed.  If 3 then XLIB handles mode switches.  Bit 4 is set if XMS is
  736.   installed.
  737.  
  738.  
  739.  
  740.  
  741.  
  742.  
  743.  
  744.                                         9
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.                                 4. Mode Switching
  752.  
  753.  
  754.        As illustrated in Example 1, CALLPM may be used to transfer control to
  755.   32-bit protected mode in segment TSEG.  When execution is returned to real
  756.   mode, segment registers, ESP, system flags, and control flags are restored to
  757.   their original values.
  758.        Execution may also be transferred to protected mode in TSEG with the
  759.   ENTERPM (enter protected mode) procedure.  This procedure is specially
  760.   designed to accommodate mixed-language programming with high-level languages
  761.   operating in real mode.  High-level language modules may be linked with
  762.   libraries containing protected-mode procedures.  These procedures may then be
  763.   called from high-level code.  However, such procedures must generally be
  764.   careful to restore register state.  ENTERPM restores register state as
  765.   required by Microsoft high-level languages.  In particular, ENTERPM restores
  766.   all registers except EAX, EDX, and the status flags.  EAX and EDX are not
  767.   restored because these are typically used by high-level languages for return
  768.   values.  ENTERPM otherwise functions exactly as CALLPM.
  769.        Both CALLPM and ENTERPM save register state as of call.  CALLPM and
  770.   ENTERPM will also save and restore the state of the floating point unit (FPU)
  771.   if requested.  FPU save/restore can be enabled by setting bit 2 of OFLAGS
  772.   (operation flags).  The bit is clear by default.  OFLAGS is a public WORD in
  773.   DSEG.
  774.        FPU state is saved with the FSAVE instruction executed from real mode.
  775.   This instruction resets the FPU; consequently, the FPU control word must be
  776.   redefined.  XLIB will therefore load FPUCW (FPU control word) to the FPU
  777.   control word after performing FSAVE.  FPUCW is a public WORD location in DSEG.
  778.        After entering protected mode through CALLPM or ENTERPM, control would
  779.   typically be returned to real mode with the RET instruction.  However, control
  780.   may also be returned to real mode by jumping to either RETPM or EXITPM.  These
  781.   are both procedures in TSEG.  They will successfully return control to real
  782.   mode regardless of the stack state; therefore, they can be useful for
  783.   debugging.  For example, an unidentified area of protected-mode code that is
  784.   causing the system to crash can be isolated by placing jumps to EXITPM at
  785.   alternative locations.
  786.        RETPM returns control to the real-mode caller of CALLPM/ENTERPM after
  787.   restoring segment registers, ESP, system flags, and control flags.  EXITPM
  788.   returns control to the real mode caller after restoring all registers except
  789.   EAX, EDX, and the status flags.
  790.        The return address placed on the stack by CALLPM is actually a near
  791.   return to RETPM.  Likewise, ENTERPM places a near return to EXITPM.  CALLPM
  792.   and ENTERPM are otherwise identical procedures.
  793.        Once within protected mode, far procedures in real mode can be called
  794.   using CALLRM.  CALLRM may be called only by protected-mode procedures in TSEG.
  795.        XLIB contains two hardware interrupt handlers that are typically
  796.   activated upon entry to protected mode.  These handlers are fully explained in
  797.   Chapter 6.  The first handler is hooked to the keyboard interrupt.  This
  798.   handler manages hot key detection.  The second handler is hooked to the FPU
  799.   interrupt and is designed to handle FPU exceptions.
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.  
  808.                                         10
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.   Detailed Specifications
  816.  
  817.  
  818.   CALLPM (Call Protected Mode)
  819.   Purpose:  Call a protected-mode procedure in TSEG with near return.
  820.   CPU Mode:  Real
  821.   Registers at Call:  SS:ESP = 32-bit protected-mode target offset.
  822.   Return Registers:  Returns through RETPM.  See RETPM for details.
  823.   Details:
  824.      All CPU registers except EAX and EDX are saved at locations presented in
  825.   Table 3.  The stack is saved after the return address and argument have been
  826.   popped.
  827.      The target receives SS = TSEGDSEL with 1000H free bytes on the stack.  The
  828.   return address on the stack is a near return to RETPM.  The target receives by
  829.   default:  DS = FLATDSEL, ES = TSEGDSEL, FS = DSEGSEL, and GS = DGROUPSEL.
  830.   Other registers, including the status flags, are received at values as of
  831.   call.
  832.      If bit 2 of OFLAGS is set, then the FPU state is also saved; the FPU is
  833.   initialized, and FPUCW is loaded to the control word.
  834.      XLIB hardware interrupt handlers are enabled (see Chapter 6).  However, if
  835.   bit 1 of OFLAGS is set, then the XLIB interrupt handler for the FPU will not
  836.   be enabled.
  837.      If an FPU exception occurs after CALLPM, and if the FPU exception handler
  838.   is enabled, then protected mode will be exited through EXITPM rather than
  839.   RETPM.  If FPU save/restore is not enabled, then real-mode will receive an
  840.   initialized FPU with control word set to the value existing as of the
  841.   exception.
  842.      The user may change the stack after the mode switch.
  843.      DS, ES, FS, and GS are actually loaded from:  PMDS, PMES, PMFS, and PMGS.
  844.   These are public WORD locations in DSEG and are initialized to the default
  845.   selectors by INITXLIB.  The user however may change these selectors to any
  846.   legal values after initialization.
  847.  
  848.   RETPM (Return From Protected Mode)
  849.   Purpose:  Return control to real mode with partial register restoration.
  850.   CPU Mode:  Protected
  851.   Registers at Call:  None
  852.   Return Registers:  No return
  853.   Details:
  854.      RETPM switches to real mode and then restores all segment registers, ESP,
  855.   system flags, and control flags to values as of call to either CALLPM or
  856.   ENTERPM.  XLIB hardware interrupt handlers are disabled (see Chapter 6).
  857.   Control is then transferred to the real-mode return address as of call to
  858.   CALLPM/ENTERPM.
  859.      If bit 2 of OFLAGS is set, then RETPM also restores FPU state.
  860.      RETPM will successfully execute regardless of stack state.
  861.  
  862.   ENTERPM (Enter Protected Mode)
  863.   Purpose:  Call a protected mode procedure in TSEG with near return.
  864.   CPU Mode:  Real
  865.   Registers at Call:  SS:ESP = 32-bit protected-mode target offset.
  866.   Return Registers:  Returns through EXITPM.  See EXITPM for details.
  867.   Details:  This routine executes exactly as CALLPM except that a near return to
  868.   EXITPM is placed on the stack rather than to RETPM.
  869.  
  870.  
  871.  
  872.                                         11
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.   EXITPM (Exit Protected Mode)
  880.   Purpose:  Return control to real mode with general register restoration.
  881.   CPU Mode:  Protected
  882.   Registers at Call:  None
  883.   Return Registers:  No return
  884.   Details:
  885.      EXITPM switches to real mode and then restores all registers except EAX,
  886.   EDX, and status flags to values as of call to either CALLPM or ENTERPM.  XLIB
  887.   hardware interrupt handlers are disabled (see Chapter 6).  Control is then
  888.   transferred to the real-mode return address as of call to CALLPM/ENTERPM.
  889.      If bit 2 of OFLAGS is set, then EXITPM also restores FPU state.
  890.      EXITPM will successfully execute regardless of stack state.
  891.      The FPU exception handler performs a jump to EXITPM upon occurrence of any
  892.   unmasked FPU exception.
  893.  
  894.  
  895.   Table 3:  CALLPM/ENTERPM Register Storage Locations by Public Symbol
  896.   _____________________________________________________________________________
  897.   Register           Symbol              Symbol Type
  898.   --------           ------              -----------
  899.   EBX                ORGEBX              DWORD
  900.   ECX                ORGECX              DWORD
  901.   ESI                ORGESI              DWORD
  902.   EDI                ORGEDI              DWORD
  903.   EBP                ORGEBP              DWORD
  904.   ESP                ORGESP              DWORD
  905.   EFLAGS             ORGEFLAGS           DWORD
  906.   SS                 ORGSS               WORD
  907.   DS                 ORGDS               WORD
  908.   ES                 ORGES               WORD
  909.   FS                 ORGFS               WORD
  910.   GS                 ORGGS               WORD
  911.   FPU State          ORGFPU              BYTE[94]
  912.   _____________________________________________________________________________
  913.  
  914.  
  915.   CALLRM (Call a Real-Mode Procedure)
  916.   Purpose:  Call a real-mode routine with far return from protected mode.
  917.   CPU Mode:  Protected
  918.   Registers at Call:  SS:ESP = far real-mode target address (four bytes).
  919.   Return Registers:  All segment registers and ESP are restored.  Other
  920.   registers, including status flags, are received with values as of the real-
  921.   mode RET instruction.
  922.   Details:
  923.      This is a near procedure in TSEG.  It must therefore be called from TSEG.
  924.      Segment registers and ESP are saved at locations presented in Table 4.  The
  925.   stack is saved after popping the return address and argument.
  926.      The target receives the XLIB real-mode stack (SS = DSEG) with 200H free
  927.   bytes.  By default, the target receives DS = DGROUP, ES = DSEG, FS = DSEG, and
  928.   GS = DSEG.  Other registers, including status flags, are received at values as
  929.   of call.
  930.      Code called by this routine should not perform calls to XLIB procedures
  931.   other than SWITCHPM and SWITCHRM (see Appendix G).  Most real-mode procedures
  932.  
  933.  
  934.  
  935.  
  936.                                         12
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.   in XLIB issue calls to CALLPM; however, neither this procedure nor ENTERPM are
  944.   reentrant.
  945.      DS and ES are actually loaded from RMDS and RMES.  These are public WORD
  946.   locations in DSEG and are initialized to the default values.  However, the
  947.   user may change these values if desired.
  948.      This procedure does not change values in OFLAGS; consequently, XLIB
  949.   hardware interrupt handlers remain enabled in real mode if they were enabled
  950.   as of call (see Chapter 6).
  951.      FPU exceptions in real mode are handled the same as in protected mode;
  952.   however, system software is less apt to be left in regular state after real-
  953.   mode exceptions.  FPU instructions should therefore be executed in protected
  954.   mode where possible.
  955.  
  956.  
  957.   Table 4:  CALLRM Register Storage Locations by Public Symbol
  958.   _____________________________________________________________________________
  959.   Register           Symbol              Symbol Type
  960.   --------           ------              -----------
  961.   ESP                CALLESP             DWORD
  962.   SS                 CALLSS              WORD
  963.   DS                 CALLDS              WORD
  964.   ES                 CALLES              WORD
  965.   FS                 CALLFS              WORD
  966.   GS                 CALLGS              WORD
  967.   _____________________________________________________________________________
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.  
  997.  
  998.  
  999.  
  1000.                                         13
  1001.  
  1002.  
  1003.  
  1004.  
  1005.  
  1006.  
  1007.                              5. Inline Mode Switching
  1008.  
  1009.  
  1010.        XLIB includes two routines to perform mode switching in C and C++
  1011.   programs using inline assembly.  These procedures are very versatile and
  1012.   simple.  They switch the processor between real mode and 16-bit protected
  1013.   mode.  A third routine is included to facilitate calls from 16-bit protected-
  1014.   mode to 32-bit near procedures in TSEG.
  1015.        Call INLINEPM to switch to 16-bit protected mode.  Descriptors are
  1016.   automatically created for CS, SS, and DS.  These registers are returned
  1017.   containing selectors to the respective descriptors.  ES is returned containing
  1018.   DSEGSEL.  ES may therefore be used to load other XLIB selectors to segment
  1019.   registers.
  1020.        Call INLINERM to return to real-mode.  This function should be called
  1021.   from the same segment as the previous call to INLINEPM and should be using the
  1022.   same stack segment.  INLINERM restores segment registers to values which
  1023.   existed as of the call to INLINEPM.
  1024.        The following Microsoft C 7.0 program illustrates the usage of these
  1025.   procedures.  The program contains a C subroutine called "getextmem" which uses
  1026.   INLINEPM and INLINERM to retrieve a DWORD from extended memory.
  1027.        Since the Microsoft C 7.0 compiler does not recognize 32-bit assembly
  1028.   instructions, the following program attains access to 32-bit registers by
  1029.   encoding prefixes in front of 16-bit instructions.  These prefixes are
  1030.   inserted with the _emit directive.  Also observe that INLINERM is called
  1031.   indirect through a supplied pointer in DSEG called INLINERMPTR.  This is done
  1032.   to ensure that the intersegment call loads CS with the protected-mode selector
  1033.   for CSEG (CSEGSEL) rather than with the segment constant.
  1034.        A Borland C version of this program is contained in the file EXAMP2B.C.
  1035.   The Borland version is somewhat simpler than the following program because 32-
  1036.   bit registers can be used in Borland C provided that TASM is used to perform
  1037.   the assembly.
  1038.        This program may fail if an attempt is made to access logical addresses
  1039.   which are either protected or undefined in the page tables.
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.                                         14
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.   Example 2:  Using INLINEPM/INLINERM in C
  1072.   _____________________________________________________________________________
  1073.   #include <stdio.h>
  1074.   #include <xlib.h>
  1075.   #define som _emit 0x66               /*Switch operand mode*/
  1076.   #define sam _emit 0x67               /*Switch address mode*/
  1077.   long __far getextmem(long address);
  1078.   int goterr = 0;                      /*Error flag*/
  1079.  
  1080.   void main(void)
  1081.   {
  1082.     long l, xaddress;
  1083.     l = INITXLIB();                    /*Initialize XLIB*/
  1084.     if(l != 0)                         /*See if an error occurred*/
  1085.     {
  1086.       printf("Library initialization error:  %lX\n",l);
  1087.       return;
  1088.     }
  1089.  
  1090.     xaddress = 0x100000;               /*Read first dword in 2ond meg*/
  1091.     l = getextmem(xaddress);           /*See if an error occurred*/
  1092.     if(goterr != 0)
  1093.     {
  1094.       printf("Inline mode-switch error:  %lX\n",l);
  1095.       return;
  1096.     }
  1097.     printf("[%lX] = %lX\n",xaddress,l);
  1098.   }
  1099.  
  1100.   long __far getextmem(long address)
  1101.   {
  1102.     __asm
  1103.     {
  1104.       som                             ;mov  eax,[bp+6]
  1105.       mov       ax,[bp+6]             ;  ""
  1106.       call      INLINEPM              ;Switch to 16-bit protected mode
  1107.       jc        error                 ;Error code in ax
  1108.       mov       ds,es:FLATDSEL        ;Switch to flat data model
  1109.       sam                             ;push dword ptr [eax]
  1110.       som                             ;  ""
  1111.       _emit     0ffh                  ;  ""
  1112.       _emit     030h                  ;  ""
  1113.       pop       ax                    ;Return address contents in dx:ax
  1114.       pop       dx
  1115.       call      es:INLINERMPTR        ;Switch back to real mode by calling
  1116.       jmp       done                  ;INLINERM indirect.  A direct call would
  1117.                                       ;load cs with an invalid value.
  1118.   error:
  1119.       xor       dx,dx                 ;Return error code in dx:ax
  1120.       inc       goterr                ;Set error flag
  1121.   done:
  1122.     }
  1123.   }
  1124.   _____________________________________________________________________________
  1125.  
  1126.  
  1127.  
  1128.                                         15
  1129.  
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135.   Detailed Specifications
  1136.  
  1137.  
  1138.   INLINEPM (Inline Protected-Mode)
  1139.   Purpose:  Return to real-mode caller in 16-bit protected mode.
  1140.   CPU Mode:  Real
  1141.   Registers at Call:  None
  1142.   Return Registers:
  1143.      CF clear if successful.  Descriptors are created for CS, SS, and DS.  These
  1144.   descriptors have base addresses matching the calling contents of the
  1145.   respective segment registers.  The segment registers are returned containing
  1146.   selectors to these descriptors.  These selectors are also stored in DSEG at
  1147.   the public WORD locations ILCSSEL, ILSSSEL, and ILDSSEL.  See Chapter 2 for
  1148.   further details as to descriptor specifications.  ES, FS, and GS are returned
  1149.   containing DSEGSEL.  Protected mode receives other registers, except the
  1150.   status flags, at values as of call.
  1151.      CF set if unsuccessful.  The processor will still be in real mode.
  1152.   Unsuccessful execution can occur only under DPMI.  EAX is returned with an
  1153.   error code.  AX = XLIB error code.  The high word of EAX will equal a DPMI 1.0
  1154.   error code (if provided by host).  Other registers, except the status flags,
  1155.   are unchanged.
  1156.   Details:
  1157.      INLINEPM stores segment registers at the same locations used by CALLPM and
  1158.   ENTERPM (Table 1).  INLINERM (see below) then restores these registers.  C
  1159.   will require that other registers be preserved also; however, the user is
  1160.   responsible for managing these.
  1161.      XLIB hardware interrupt handlers are not activated by this procedure (see
  1162.   Chapter 6).  The keyboard handler may be enabled by the user if hot key
  1163.   detection is needful; however, the FPU exception handler should never be
  1164.   enabled.  Therefore, hot key detection should be enabled by setting both bits
  1165.   0 and 1 in OFLAGS.
  1166.      SP is preserved through the mode switch; however, the high word of ESP is
  1167.   set to zero.  The high word must be cleared since SS is set to a descriptor
  1168.   having FFFFH limit and having its big bit set.
  1169.      If multiple calls are made to INLINEPM with the same values in CS, SS, and
  1170.   DS, then descriptors are created only on the first call.  Subsequent calls
  1171.   will therefore execute more quickly.
  1172.  
  1173.   INLINERM (Inline Real-Mode)
  1174.   Purpose:  Return to 16-bit protected-mode caller in real mode.
  1175.   CPU Mode:  16-bit protected mode
  1176.   Registers at Call:  CS and SS must equal values as of return from INLINEPM.
  1177.   Return Registers:  Segment registers are restored to values existing as of
  1178.   former call to INLINEPM.  Real mode receives other registers, except status
  1179.   flags, at values as of call.
  1180.   Details:
  1181.      Since INLINERM will be called intersegment, caution must be taken that CS
  1182.   is loaded with CSEGSEL and not CSEG.  XLIB provides a far pointer to this
  1183.   procedure called INLINERMPTR which may be used to execute the call.
  1184.      INLINERM and CALL32 are the only 16-bit protected-mode procedures in XLIB.
  1185.   They are also the only protected-mode procedures having far returns.
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.                                         16
  1193.  
  1194.  
  1195.  
  1196.  
  1197.  
  1198.  
  1199.   CALL32 (Call 32-bit Protected-Mode)
  1200.   Purpose:  Call a 32-bit protected-mode near procedure in segment TSEG from 16-
  1201.   bit protected-mode.
  1202.   CPU Mode:  16-bit protected mode
  1203.   Registers at Call:  SS:ESP =  32-bit protected-mode target offset.
  1204.   Return Registers:  All registers, including status flags, are returned with
  1205.   values existing as of the 32-bit RET instruction.
  1206.   Details:
  1207.      CALL32 is a far procedure; therefore, caution must be taken that calls to
  1208.   CALL32 load CS with CSEGSEL instead of CSEG.  XLIB provides a far pointer to
  1209.   this procedure in DSEG called CALL32PTR which may be used to execute the call.
  1210.      CALL32 and INLINERM are the only 16-bit protected-mode procedures in XLIB.
  1211.   They are also the only protected-mode procedures having far returns.
  1212.      This procedure does not alter the state of OFLAGS.
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.                                         17
  1257.  
  1258.  
  1259.  
  1260.  
  1261.  
  1262.  
  1263.                              6. Interrupt Management
  1264.  
  1265.  
  1266.        Interrupt management is the most complicated task performed by XLIB.
  1267.   Accordingly, this chapter is the most difficult section of the user's manual.
  1268.   In general, this chapter may be ignored for programs which do not install
  1269.   interrupt handlers, do not require hot key detection, and do not use floating
  1270.   point operations.
  1271.  
  1272.  
  1273.   XLIB Interrupt Handlers
  1274.  
  1275.  
  1276.        XLIB handles nearly all interrupts occurring in protected mode by
  1277.   shifting to real mode and calling the currently installed real-mode interrupt
  1278.   handlers.  In all but three cases, XLIB uses inherited real-mode handlers.
  1279.   XLIB installs its own handlers only for the DOS interrupt (INT 21H), the
  1280.   keyboard interrupt (INT 9), and the FPU interrupt (INT 75H).
  1281.        The DOS interrupt handler (INT 21H) intercepts all DOS calls and
  1282.   determines if termination is requested (AH = 4CH).  If not, then the interrupt
  1283.   is immediately cascaded to DOS.  If so, then XLIB performs housecleaning
  1284.   before relaying the request to DOS.  Under DPMI, XLIB will restore all
  1285.   interrupt vectors and release all allocated descriptors.  The DPMI host
  1286.   automatically releases all allocated memory.  Under other configurations, XLIB
  1287.   will reset all real-mode interrupt vectors and release all allocated extended
  1288.   memory.
  1289.        INT 21H function 4CH may be executed in either real mode or protected
  1290.   mode.  DPMI hosts will expect this function to be executed from protected
  1291.   mode; consequently, XLIB will switch to protected mode before relaying the
  1292.   request to DPMI.  XLIB also installs a protected-mode handler for INT 21H
  1293.   under DPMI.  This is to ensure that XLIB will see the termination request
  1294.   before the DPMI host.
  1295.        The keyboard interrupt handler is intended to facilitate termination of
  1296.   protected-mode procedures with a keypress.  When a user-defined hot key is
  1297.   pressed, the keyboard interrupt handler will modify a flag variable.  This
  1298.   flag variable may then be polled periodically in the main thread of execution.
  1299.   The keyboard interrupt handler is a real-mode routine.
  1300.        The inconvenience of having to poll the flag variable is unfortunately
  1301.   necessary.  It is not generally safe to terminate within a hardware interrupt
  1302.   handler, particularly in protected-mode environments.  A hardware interrupt
  1303.   generated by a keypress may have interrupted system software in the middle of
  1304.   a system maintenance operation.  Termination in such cases would likely leave
  1305.   the system in an irregular and potentially unstable state.
  1306.        Matters are further complicated in most protected-mode environments.  For
  1307.   example, a DPMI host will trap all hardware interrupts before cascading them
  1308.   to interrupt handlers.  If control is not returned to the host with the IRET
  1309.   instruction, then the host will be left in an irregular state.  Moreover, the
  1310.   trapping procedure will likely switch stacks before relaying the interrupt to
  1311.   the handler; consequently, the handler cannot determine the final return
  1312.   address and therefore cannot change this address to a termination procedure.
  1313.   These complications will nearly always occur when hardware interrupts are
  1314.   virtualized.  Virtual 8086 mode interrupts will almost certainly be
  1315.   virtualized in either VCPI-based or DPMI-based environments.
  1316.  
  1317.  
  1318.  
  1319.  
  1320.                                         18
  1321.  
  1322.  
  1323.  
  1324.  
  1325.  
  1326.  
  1327.        When a key is pressed, the keyboard interrupt handler will examine the
  1328.   key to determine if it is the hot key.  If not, then the interrupt is cascaded
  1329.   to the inherited real-mode handler.  If so, then a hot key flag is recorded to
  1330.   a DWORD whose linear address is recorded at CCODEPTR (condition code pointer).
  1331.   The hot key is not cascaded.  CCODEPTR is a public DWORD in DSEG.  The hot key
  1332.   flag is listed among XLIB error codes in Appendix B.
  1333.        CCODEPTR initially contains the linear address to public DWORD location
  1334.   CCODE which is in DSEG.  Therefore, the hot key flag would be written to CCODE
  1335.   by default.  CCODEPTR may be changed by the user; however, it must point to an
  1336.   address in conventional memory.
  1337.        The hot key specification is stored in DSEG at a public WORD location
  1338.   called HOTKEY.  The lower byte of HOTKEY contains the scan code of the hot key
  1339.   while the upper byte specifies the state of the shift keys.  Bit 8 specifies
  1340.   the state of SHIFT; bit 9 specifies CTRL, and bit 10 specifies ALT.  All other
  1341.   bits are ignored.  Set bits require that the designated shift key be pressed.
  1342.   The default setting for HOTKEY is zero.  This setting disables hot key
  1343.   detection since no key has a zero scan code.
  1344.        The XLIB interrupt handler for FPU exceptions performs three major
  1345.   functions upon the occurrence of any FPU exception that is unmasked in the FPU
  1346.   control word.  First, an error code is loaded to EAX and is also recorded at
  1347.   the linear address in CCODEPTR.  Next, the FPU is initialized with FNINIT (the
  1348.   FPU control word is preserved).  Third, control is transferred to EXITPM to
  1349.   return to real mode.  The high word stored in EAX and in the condition code
  1350.   will be the FPU status word.  This word may be examined to determine the
  1351.   nature of the exception.  The FPU interrupt handler is a real-mode routine.
  1352.        The response of the FPU to exception conditions is largely determined by
  1353.   the settings in the FPU control word.  If FPU save/restore is enabled, then
  1354.   the FPU control word will be set to FPUCW upon execution of CALLPM/ENTERPM.
  1355.   The default value for FPUCW is 0332H.  This sets rounding control to nearest,
  1356.   precision control to 64 bits, and unmasks exceptions for overflow, zero
  1357.   divide, and invalid operations.  Exceptions for underflow, precision, and
  1358.   denormalized operations are masked, and are therefore handled internally by
  1359.   the FPU.  FPUCW may be modified by the user.
  1360.        As explained above, the machine may be left in an unstable state after a
  1361.   program has been terminated from within a hardware interrupt handler.  This
  1362.   can also be the case for the FPU interrupt handler.  However, it will be safe
  1363.   to continue execution after FPU exceptions under clean configurations.  This
  1364.   follows because interrupts are not virtualized and because the exception will
  1365.   never be generated in the operating system (DOS does not use the FPU).  Nor
  1366.   should there be any problem with continuing execution after an exception in
  1367.   protected-mode under VCPI.  This follows since protected-mode interrupts
  1368.   cannot be virtualized under VCPI.  Exceptions occurring in virtual 8086 mode
  1369.   or under DPMI protected mode may however leave the machine in an irregular
  1370.   state.  Reboot may be necessary in these cases.
  1371.        All tested DPMI hosts appear to be restored to normal state by execution
  1372.   of INT 21H function 4CH (DOS termination).  However, the DPMI specifications
  1373.   offer no guarantees to this approach.  FPU exceptions in virtual 8086 mode are
  1374.   generally no problem in single-task environments; however, they will
  1375.   frequently prove problematic under a multitasker such as DESQview.
  1376.        Bit 0 of OFLAGS is used by XLIB to simultaneously enable or disable all
  1377.   of its own hardware interrupt handlers.  Setting the bit enables the handlers.
  1378.   XLIB sets this bit upon calls to CALLPM/ENTERPM and clears the bit upon
  1379.   return.  All interrupts are immediately cascaded to the inherited real-mode
  1380.   handlers when the bit is clear.  Therefore, FPU exceptions are handled by XLIB
  1381.  
  1382.  
  1383.  
  1384.                                         19
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391.   only after calls to CALLPM/ENTERPM.  Accordingly, hot key detection is enabled
  1392.   only after calls to CALLPM/ENTERPM.  The user may set the bit under other
  1393.   circumstances; however, XLIB will not be able to properly handle FPU
  1394.   exceptions in these cases.  The bit should be set by the user only when hot
  1395.   key detection is desired and when it is certain that the FPU exception handler
  1396.   will not be invoked.
  1397.        The FPU exception handler may be permanently disabled by setting bit 1 in
  1398.   OFLAGS.  If this bit is set, then the FPU interrupt handler simply cascades
  1399.   the interrupt to the inherited real-mode handler.  XLIB will set the bit
  1400.   during initialization if an FPU is not present; it is otherwise cleared.
  1401.        Real-mode software interrupts which receive or return values in segment
  1402.   registers cannot be used within protected mode because the deflection routine
  1403.   will restore selectors to segment registers upon completion of the interrupt.
  1404.   To use such software interrupts, one must switch to real mode through CALLRM;
  1405.   issue the interrupt, and then transfer the segment registers to other
  1406.   registers or to memory before returning to protected mode.
  1407.        Certain software interrupts use status flags for return flags, typically
  1408.   to signal error conditions.  This is particularly the case for DOS interrupts.
  1409.   The deflection routine will pass these alterations to the code which issued
  1410.   the interrupt.
  1411.  
  1412.  
  1413.   Installation of Interrupt Handlers
  1414.  
  1415.  
  1416.        The user may install real-mode interrupt handlers in usual fashion.  Such
  1417.   handlers will also receive interrupts occurring in protected mode because
  1418.   either XLIB or the DPMI host will deflect all protected-mode interrupts.  If
  1419.   XLIB deflects the interrupt, then the handler will receive SS = DSEG with ESP
  1420.   set to 100H free bytes.  Stack sizes under DPMI will depend upon the host, but
  1421.   must contain a minimum of 200H free bytes to meet DPMI specifications.
  1422.        The DOS routines to get and set interrupt vectors (INT 21H functions 35H
  1423.   and 25H) receive and return values through segment registers; consequently,
  1424.   they cannot be used in protected mode.  Instead, use the XLIB procedures
  1425.   PMGETRMIV and PMSETRMIV (protected mode - get/set real-mode interrupt vector).
  1426.        The user may install a protected-mode interrupt handler from real mode by
  1427.   calling SETPMIV (set protected-mode interrupt vector).  The current protected-
  1428.   mode interrupt vector may be obtained by calling GETPMIV.
  1429.        From protected mode, interrupt vectors can be managed with PMSETPMIV and
  1430.   PMGETPMIV.  These procedures have the same specifications as SETPMIV and
  1431.   GETPMIV.
  1432.        Interrupt handlers installed with SETPMIV/PMSETPMIV are never disabled by
  1433.   XLIB and will therefore always be active under protected-mode execution.
  1434.   These handlers will not be active under real-mode execution in the absence of
  1435.   DPMI.  That is, real-mode interrupts are never deflected to protected-mode
  1436.   handlers in such environments.  However if DPMI is active, then all hardware
  1437.   interrupts (IRQs 0-15) and the software interrupts:  1CH (BIOS timer tick),
  1438.   23H (DOS CTRL C), and 24H (DOS critical error) are deflected from real mode to
  1439.   the installed protected-mode handler.  Therefore the protected-mode handler
  1440.   always receives the interrupt first.  If the handler cascades the interrupt,
  1441.   then the real-mode handler will receive it next.  If the user has not
  1442.   installed protected-mode handlers for these interrupts, then they are serviced
  1443.   by default handlers in the DPMI host.  The default handlers typically deflect
  1444.   the interrupts to the real-mode handlers.
  1445.  
  1446.  
  1447.  
  1448.                                         20
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.        If the programmer wishes to install a protected-mode interrupt handler
  1456.   for a hardware interrupt or for INT 1CH, INT 23H, or INT 24H, then
  1457.   consideration must be given to the fact that treatment of these interrupts
  1458.   will differ under different protected-mode configurations.  As noted above,
  1459.   the DPMI host will always send these interrupts to the protected-mode handler
  1460.   regardless of the CPU mode in which the interrupt occurred.  If DPMI is not
  1461.   installed, then protected-mode handlers receive control only under protected-
  1462.   mode interrupts.  Therefore, if the protected-mode handler is to receive real-
  1463.   mode interrupts under such configurations, the programmer must install a real-
  1464.   mode handler to perform the deflection.
  1465.        XLIB includes a procedure called DEFLECTPM which can be used within a
  1466.   real-mode interrupt handler to deflect control to a protected-mode handler.
  1467.   DEFLECTPM functions only under VCPI and XLIB mode switching.  If DPMI is
  1468.   installed, then the procedure returns with no action.  The intent of this
  1469.   procedure is to enable simulation of DPMI treatment of hardware interrupts,
  1470.   INT 1CH, INT 23H, and INT 24H.
  1471.        Observe that if the real-mode handler deflects to the protected-mode
  1472.   handler, then the latter should not cascade the interrupt since an infinite
  1473.   loop would result.  This follows because the initial protected-mode handler
  1474.   deflects to the real-mode handler.
  1475.        Were one to use DEFLECTPM in a real-mode handler for the interrupts named
  1476.   above, then the protected-mode handler will receive all interrupts regardless
  1477.   of the protected-mode configuration.  This occurs naturally under DPMI.
  1478.   DEFLECTPM ensures that it will occur under other configurations.  Observe that
  1479.   under DPMI, the real-mode handler will never be executed.
  1480.        It is sometimes important that interrupt handlers execute in shortest
  1481.   possible CPU time.  This would typically be the case for handlers of the
  1482.   communication ports.  Since mode switching is time consuming, such handlers
  1483.   should be installed for the CPU mode which is expected to receive the most
  1484.   interrupts.
  1485.        If DPMI is installed, then it is possible for multiple clients to operate
  1486.   in a single virtual machine.  In such cases, DPMI will always send hardware
  1487.   interrupts to the primary client (the most recently installed client in the
  1488.   virtual machine).
  1489.        Under DPMI, all protected-mode handlers for hardware interrupts and
  1490.   software interrupts 0-7 will receive control with interrupts disabled.  Since
  1491.   DPMI virtualizes the interrupt flag, the IRET instruction may not reenable
  1492.   interrupts.  Consequently, all handlers for these interrupts should execute
  1493.   STI before executing IRET.  Other protected-mode interrupts do not affect the
  1494.   interrupt flag.
  1495.        All real-mode interrupt handlers will receive control with interrupts
  1496.   disabled regardless of the protected-mode configuration.  All protected-mode
  1497.   handlers will receive control with interrupts disabled under VCPI or XLIB mode
  1498.   switching.  However, if DPMI is installed, then protected-mode software
  1499.   interrupts apart from 0-7 will receive the virtual interrupt flag at its value
  1500.   as of the INT instruction.  That is, DPMI does not alter the interrupt flag in
  1501.   these cases.
  1502.        Hardware interrupts IRQ 0 through IRQ 7 are typically assigned to
  1503.   interrupt numbers 08H through 0FH, while IRQs 8 through 15 are typically
  1504.   assigned interrupt numbers 70H through 77H.  However, IRQs are remapped in
  1505.   some operating environments, typically to facilitate exception handling.  The
  1506.   current mappings may be loaded from IRQ0INTNO (IRQ 0 interrupt number) and
  1507.   IRQ8INTNO.  These are public BYTE locations in DSEG.  They should be read only
  1508.   after the call to INITXLIB.
  1509.  
  1510.  
  1511.  
  1512.                                         21
  1513.  
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.        DESQview does remap hardware interrupts; however, its interrupt handlers
  1520.   for the new locations generally transfer control to the addresses at the
  1521.   conventional vectors.  DESQview must be started with a command-line switch if
  1522.   it is to accommodate certain hardware interrupts.  In particular, the FPU
  1523.   interrupt will not function properly under DESQview unless DESQview is started
  1524.   with DV /HW:75:C.
  1525.  
  1526.  
  1527.   Detailed Specifications
  1528.  
  1529.  
  1530.   PMGETRMIV (Protected Mode - Get Real-Mode Interrupt Vector)
  1531.   Purpose:  Retrieve address of real-mode interrupt handler.
  1532.   CPU Mode:  Protected
  1533.   Registers at Call:  AL = interrupt number.
  1534.   Return Registers:  Handler address returned in CX:DX.
  1535.   Details:  The DOS routine for this purpose (INT 21H function 35H) is not
  1536.   useful because it returns a value in ES.
  1537.  
  1538.   PMSETRMIV (Protected Mode - Set Real-Mode Interrupt Vector)
  1539.   Purpose:  Set address of real-mode interrupt handler.
  1540.   CPU Mode:  Protected
  1541.   Registers at Call:  AL = interrupt number, CX:DX = address of handler.
  1542.   Return Registers:  None
  1543.   Details:
  1544.      The DOS routine for this purpose (INT 21H function 25H) is not useful
  1545.   because it requires an argument in DS.
  1546.      Real-mode interrupt handlers will also be called when interrupts occur in
  1547.   protected mode provided that the protected-mode interrupt handler cascades the
  1548.   interrupt.  The default protected-mode handlers do in fact cascade all
  1549.   interrupts.
  1550.      XLIB never disables handlers installed by this procedure.
  1551.  
  1552.   GETPMIV (Get Protected-Mode Interrupt Vector)
  1553.   Purpose:  Retrieve address of protected-mode interrupt handler from interrupt
  1554.   descriptor table.
  1555.   CPU Mode:  Real
  1556.   Registers at Call:  AL = interrupt number.
  1557.   Return Registers:  Handler address returned in CX:EDX (CX is a selector).
  1558.   Details:  This routine does not return addresses of CPU exception handlers
  1559.   under DPMI.  Use DPMI functions directly for this purpose.
  1560.  
  1561.   SETPMIV (Set Protected-Mode Interrupt Vector)
  1562.   Purpose:  Set address of protected-mode interrupt handler in interrupt
  1563.   descriptor table.
  1564.   CPU Mode:  Real
  1565.   Registers at Call:  AL = interrupt number.  Handler address in CX:EDX (CX is a
  1566.   selector).
  1567.   Return Registers:  EAX = 0 if successful.  EAX = error code if unsuccessful.
  1568.   AX = XLIB error code.  If DPMI is installed then the high word of EAX will
  1569.   contain a DPMI 1.0 error code (if provided by host).
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.                                         22
  1577.  
  1578.  
  1579.  
  1580.  
  1581.  
  1582.  
  1583.   Details:
  1584.      XLIB never disables handlers installed by this procedure.
  1585.      Protected-mode interrupt handlers never receive interrupts occurring in
  1586.   real mode unless DPMI is active.  Under DPMI all hardware interrupts (IRQs 0-
  1587.   15) and software interrupts 1CH, 23H, and 24H are deflected from real mode to
  1588.   the installed protected-mode handler.  The protected-mode handler therefore
  1589.   receives control of the interrupt first.  It may cascade the interrupt if so
  1590.   desired, in which event, the real-mode handler receives the interrupt next. If
  1591.   no protected-mode handler has been installed, then DPMI generally deflects the
  1592.   interrupt to the real-mode handler.
  1593.      All protected-mode handlers will receive control with interrupts disabled
  1594.   unless DPMI is installed.  Under DPMI, protected-mode software interrupts
  1595.   apart from 0-7 do not alter the state of the virtual interrupt flag.
  1596.      Protected-mode handlers under DPMI for hardware interrupts and software
  1597.   interrupts 0-7 should execute STI before IRET to ensure that the virtual
  1598.   interrupt flag is enabled.
  1599.      If multiple DPMI clients are running in the same virtual machine, then the
  1600.   primary client (most recently installed client) always receives hardware
  1601.   interrupts.
  1602.      If DPMI is installed, then protected-mode interrupt vectors should be reset
  1603.   to original values before termination.
  1604.      This routine should not be used to install CPU exception handlers under
  1605.   DPMI.  DPMI functions should be used for this purpose.
  1606.  
  1607.   PMGETPMIV (Protected Mode - Get Protected-Mode Interrupt Vector)
  1608.   Purpose:  Retrieve address of protected-mode interrupt handler from interrupt
  1609.   descriptor table.
  1610.   CPU Mode:  Protected
  1611.   Details:  This routine is the protected-mode version of GETPMIV.  See GETPMIV
  1612.   for specifications.
  1613.  
  1614.   PMSETPMIV (Protected Mode - Set Protected-Mode Interrupt Vector)
  1615.   Purpose:  Set address of protected-mode interrupt handler in interrupt
  1616.   descriptor table.
  1617.   CPU Mode:  Protected
  1618.   Details:  This routine is the protected-mode version of SETPMIV.  See SETPMIV
  1619.   for specifications.
  1620.  
  1621.   DEFLECTPM (Deflect to Protected-Mode)
  1622.   Purpose:  Call a protected-mode interrupt handler.
  1623.   CPU Mode:  Real
  1624.   Registers at Call:  SS:ESP = interrupt number (2 bytes)
  1625.   Return Registers:  All registers except segment registers and ESP are returned
  1626.   at values as of the protected-mode IRET instruction.
  1627.   Details:
  1628.      This procedure can be used only under VCPI and XLIB mode switching.  It
  1629.   returns with no action under DPMI.  The routine is intended to simulate DPMI
  1630.   treatment of hardware interrupts, INT 1CH, INT 23H, and INT24H.  The routine
  1631.   may be called from a real-mode interrupt handler to deflect the interrupt to
  1632.   the protected-mode handler.
  1633.      The protected-mode handler should not cascade the interrupt; otherwise, an
  1634.   infinite loop will result.
  1635.  
  1636.  
  1637.  
  1638.  
  1639.  
  1640.                                         23
  1641.  
  1642.  
  1643.  
  1644.  
  1645.  
  1646.  
  1647.                                7. Memory Management
  1648.  
  1649.  
  1650.        XLIB supplies memory management procedures for both real and protected
  1651.   modes.  These procedures are configured at initialization to work with the
  1652.   currently resident memory management interfaces.
  1653.        Conventional memory may be allocated and released in real mode through
  1654.   DOS in usual fashion (INT 21H functions 48H and 49H).  However, DOS functions
  1655.   may not work properly in protected mode.  Therefore, use the XLIB routines
  1656.   PMGETDOSMEM and PMFREEDOSMEM for such requests.  PMFREEDOSMEM can also be used
  1657.   to find the amount of available DOS memory.
  1658.        The real-mode extended memory management procedures are GETMEM, FREEMEM,
  1659.   and RESETMEM.  GETMEM is used to allocate a block of extended memory.  FREEMEM
  1660.   may then be used to release the block.  RESETMEM releases all previously
  1661.   allocated blocks at once.  GETMEM may also be used to find the amount of
  1662.   available extended memory.
  1663.        The protected-mode memory management procedures are PMGETMEM, PMFREEMEM,
  1664.   and PMRESETMEM.  These procedures function exactly as the corresponding real-
  1665.   mode procedures:  GETMEM, FREEMEM, and RESETMEM.
  1666.        XLIB will seek extended memory through XMS only if it is present and if
  1667.   both DPMI and VCPI are absent.  If either protected-mode interface is present,
  1668.   then all extended memory will be allocated through the configured interface.
  1669.        XLIB will not use XMS to allocate memory from the high memory area (HMA)
  1670.   or from upper memory blocks (UMBs).  XLIB will however allocate from the HMA
  1671.   when it has full responsibility for extended memory management (DPMI, VCPI,
  1672.   and XMS are all absent).  XLIB never issues calls under the Expanded Memory
  1673.   Specification (EMS).
  1674.        Under DPMI and VCPI, the CPU will typically be operating in page mode.
  1675.   Under this mode of operation, memory may be remapped such that logical
  1676.   addresses are not equal to physical addresses.  Addresses specified in the
  1677.   instruction code are logical addresses.  The physical addresses are the
  1678.   locations in memory which are actually accessed.  Typically, a programmer need
  1679.   not be concerned with the difference between these two types of addresses.
  1680.   However, the difference must be recognized when working with input/output
  1681.   devices which map to certain physical location in memory.  XLIB includes
  1682.   routines called MAPIO and PMMAPIO which assign a logical addresses to a
  1683.   specified physical addresses.  The physical addresses can then be accessed via
  1684.   the assigned logical addresses.
  1685.  
  1686.  
  1687.   Detailed Specifications
  1688.  
  1689.  
  1690.   PMGETDOSMEM (Protected Mode - Get DOS Memory)
  1691.   Purpose:  Allocate DOS memory block.
  1692.   CPU Mode:  Protected
  1693.   Registers at Call:  EAX = desired size of block in bytes.
  1694.   Return Registers:
  1695.      EAX = 0 if successful.  A block handle is returned in EBX.  The number of
  1696.   allocated bytes is returned in ECX.  The linear address of allocated block is
  1697.   returned in EDX.
  1698.      EAX = error code if unsuccessful.  AX = XLIB error code.  The high word of
  1699.   EAX (EAH) will be set to a DOS error code.  If DPMI is active, then EAH will
  1700.   be a DPMI error code (codes are supplied by DPMI .9 and up).
  1701.  
  1702.  
  1703.  
  1704.                                         24
  1705.  
  1706.  
  1707.  
  1708.  
  1709.  
  1710.  
  1711.   Details:
  1712.      The block will always be paragraph aligned and will have size equal to an
  1713.   integer multiple of 16.
  1714.      The location in free memory from which the block is allocated will depend
  1715.   upon the allocation strategy in force as of call (see INT 21H function 58H).
  1716.      Call with EAX = 0 to get largest available DOS memory block (not total free
  1717.   memory) in ECX (EAX, EBX, and EDX are preserved).
  1718.      If DPMI is active, then the handle is actually a selector with base address
  1719.   set to the linear address of the block.  If DPMI is not active, then the
  1720.   handle will be the segment of the block.
  1721.      In real mode, DOS memory may be allocated directly from DOS (INT 21H
  1722.   function 48H); however, this call will likely fail under DPMI protected mode.
  1723.  
  1724.   PMFREEDOSMEM (Protected Mode - Free DOS Memory)
  1725.   Purpose:  Release previously allocated DOS memory block.
  1726.   CPU Mode:  Protected
  1727.   Registers at Call:  EAX = block handle.
  1728.   Return Registers:  EAX = 0 if successful; otherwise, EAX = error code.  AX =
  1729.   XLIB error.  The high word of EAX (EAH) will be a DOS error code.  If DPMI is
  1730.   active, then EAH will equal a DPMI error code (codes are supplied by DPMI .9
  1731.   and up).
  1732.   Details:  In real mode, DOS memory may be released directly by DOS (INT 21H
  1733.   function 49H); however, this call will likely fail under DPMI protected mode.
  1734.  
  1735.   GETMEM (Get Memory)
  1736.   Purpose:  Allocate extended memory block.
  1737.   CPU Mode:  Real
  1738.   Registers at Call:  EAX = desired size of block in bytes.
  1739.   Return Registers:
  1740.      EAX = 0 if successful.  A block handle is returned in EBX.  The number of
  1741.   allocated bytes is returned in ECX.  The logical address of allocated block is
  1742.   returned in EDX.
  1743.      EAX = error code if unsuccessful.  AX = XLIB error code.  If DPMI is
  1744.   active, then the high word of EAX (EAH) will be a DPMI 1.0 error code (if
  1745.   provided by host).  If XMS is active, then EAH = XMS error code.
  1746.   Details:
  1747.      The page size for extended memory allocations is contained in PAGESIZE.
  1748.   PAGESIZE is a DWORD in DSEG and should be read after initialization.  The
  1749.   blocks will have addresses that are PAGESIZE aligned and will have sizes equal
  1750.   to an integer multiple of PAGESIZE.  PAGESIZE will equal:  1024 for XMS, 4096
  1751.   for VCPI, 4096 for most DPMI hosts, and 16 in the absence of a memory manager.
  1752.      If XMS is present in conjunction with either DPMI or VCPI, no extended
  1753.   memory will be requested through XMS.  All extended memory will be requested
  1754.   through the active protected-mode interface.
  1755.      XMS is never used to allocate from the HMA or from UMBs.  XLIB will however
  1756.   allocate from the HMA in the absence of a memory management interface.
  1757.      Call with EAX = 0 to get largest available extended memory block (not total
  1758.   free memory) in ECX (EBX and EDX are preserved).  This call can also return
  1759.   with an error condition in EAX.
  1760.  
  1761.  
  1762.  
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.                                         25
  1769.  
  1770.  
  1771.  
  1772.  
  1773.  
  1774.  
  1775.   FREEMEM (Free Memory)
  1776.   Purpose:  Release previously allocated extended memory block.
  1777.   CPU Mode:  Real
  1778.   Registers at Call:  EAX = block handle.
  1779.   Return Registers:  EAX = 0 if successful; otherwise, EAX = error code.  AX =
  1780.   XLIB error code.  If DPMI is active, then the high word of EAX (EAH) will be a
  1781.   DPMI 1.0 error code (if provided by host).  If XMS is active, then EAH = XMS
  1782.   error code.
  1783.   Details:  FREEMEM does not release page tables allocated under VCPI.  Call
  1784.   RESETMEM for this purpose.
  1785.  
  1786.   RESETMEM (Reset Memory)
  1787.   Purpose:  Release all previously allocated extended memory.
  1788.   CPU Mode:  Real
  1789.   Registers at Call:  None
  1790.   Return Registers:  EAX = 0 if successful; otherwise, EAX = error code.  AX =
  1791.   XLIB error code.  If DPMI is active, then the high word of EAX (EAH) will be a
  1792.   DPMI 1.0 error code (if provided by host).  If XMS is active, then EAH = XMS
  1793.   error code.
  1794.   Details:
  1795.      GETMEM will automatically allocate page tables as needed under VCPI.
  1796.   RESETMEM will release such tables.
  1797.      If DPMI is not installed, then RESETMEM will be called upon execution of
  1798.   INT 21H function 4C (DOS termination).  DPMI hosts reset extended memory
  1799.   automatically.
  1800.  
  1801.   PMGETMEM  (Protected Mode - Get Memory)
  1802.   Purpose:  Allocate extended memory block.
  1803.   CPU Mode:  Protected
  1804.   Details:  This routine is the protected-mode version of GETMEM.  See GETMEM
  1805.   for specifications.
  1806.  
  1807.   PMFREEMEM  (Protected Mode - Free Memory)
  1808.   Purpose:  Free previously allocated extended memory block.
  1809.   CPU Mode:  Protected
  1810.   Details:  This routine is the protected-mode version of FREEMEM.  See FREEMEM
  1811.   for specifications.
  1812.  
  1813.   PMRESETMEM (Protected Mode - Reset Memory)
  1814.   Purpose:  Free all previously allocated extended memory.
  1815.   CPU Mode:  Protected
  1816.   Details:  This routine is the protected-mode version of RESETMEM.  See
  1817.   RESETMEM for specifications.
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825.  
  1826.  
  1827.  
  1828.  
  1829.  
  1830.  
  1831.  
  1832.                                         26
  1833.  
  1834.  
  1835.  
  1836.  
  1837.  
  1838.  
  1839.   MAPIO (Map Input/Output Device)
  1840.   Purpose:  Create a logical address mapping for an input/output device which
  1841.   maps to a fixed physical memory address.
  1842.   CPU Mode:  Real
  1843.   Registers at Call:  EDX = first physical address to be mapped.  EAX = size of
  1844.   physical address block.
  1845.   Return Registers:
  1846.      EAX = 0 if successful, in which event, EDX = the logical address for
  1847.   accessing the physical memory.
  1848.      EAX = error code if unsuccessful.  AX = XLIB error code.  If DPMI is
  1849.   active, then the high word of EAX (EAH) will be a DPMI 1.0 error code (if
  1850.   provided by host).  If XMS is active, then EAH = XMS error code.
  1851.   Details:
  1852.      DPMI will not allow mapping of physical addresses within the first
  1853.   megabyte; however, such mappings are allowed under other configurations.
  1854.      Logical addresses will always equal physical addresses in the absence of
  1855.   VCPI and DPMI because the processor will not be operating in page mode.  In
  1856.   such cases, MAPIO simply performs validity checks on EDX and EAX.
  1857.      MAPIO will automatically allocate page tables as needed under VCPI.
  1858.   RESETMEM will release such tables.
  1859.      Memory-mapped input/output devices are not typically mapped within the
  1860.   range of available memory since this would leave the possibility of confusing
  1861.   such addresses with ordinary memory.  Instead, such devices are mapped beyond
  1862.   the highest address that would otherwise be available.
  1863.  
  1864.   PMMAPIO (Protected Mode - Map Input/Output Device)
  1865.   Purpose:  Create a logical address mapping for an input/output device which
  1866.   maps to a fixed physical memory address.
  1867.   CPU Mode:  Protected
  1868.   Details:  This routine is the protected-mode version of MAPIO.  See MAPIO for
  1869.   specifications.
  1870.  
  1871.  
  1872.  
  1873.  
  1874.  
  1875.  
  1876.  
  1877.  
  1878.  
  1879.  
  1880.  
  1881.  
  1882.  
  1883.  
  1884.  
  1885.  
  1886.  
  1887.  
  1888.  
  1889.  
  1890.  
  1891.  
  1892.  
  1893.  
  1894.  
  1895.  
  1896.                                         27
  1897.  
  1898.  
  1899.  
  1900.  
  1901.  
  1902.  
  1903.                                 8. File Management
  1904.  
  1905.  
  1906.        XLIB file management procedures are low-level routines with powerful
  1907.   capabilities.  These routines can load files to extended memory or save
  1908.   extended memory to files.  They can read and write files either sequentially
  1909.   or randomly.
  1910.        All XLIB file management routines will receive and return values in a
  1911.   contiguous block of memory called a "file control block" (not to be confused
  1912.   with DOS file control blocks).  The file control block must be located in
  1913.   conventional memory and must have the form presented in Table 5.
  1914.  
  1915.  
  1916.   Table 5:  XLIB File Control Block Structure
  1917.   _____________________________________________________________________________
  1918.   Field Name   Field Type        Field Description
  1919.   ----------   ----------        -----------------
  1920.   CONDCODE     DWORD             Condition code from file operation
  1921.   FNAME        BYTE[68]          File path and name (zero terminated string)
  1922.   FHANDLE      WORD              File handle assigned by DOS
  1923.   FPTRMODE     WORD              File pointer mode
  1924.   FPTR         DWORD             File pointer
  1925.   BLKADR       DWORD             Memory source/destination address
  1926.   BLKSIZE      DWORD             Size of transfer block in bytes
  1927.   BUFADR       DWORD             Buffer address (conventional memory address)
  1928.   BUFSIZE      WORD              Buffer size in bytes
  1929.   CONTROL      WORD              Control word
  1930.   _____________________________________________________________________________
  1931.  
  1932.  
  1933.        CONDCODE is used to return error codes.
  1934.        FNAME is a zero-terminated ASCII string defining the file path and name.
  1935.   There cannot be more than 67 characters in this string, excluding the
  1936.   termination character.
  1937.        BLKADR and BLKSIZE define the source/destination memory block for the
  1938.   transfer.  This block may be in either conventional or extended memory.
  1939.   BLKADR is a linear address.
  1940.        XLIB uses DOS to access the disk.  DOS cannot read or write to extended
  1941.   memory; consequently, a conventional memory buffer must be set up for the DOS
  1942.   transfers.  File management routines shift to protected mode to perform
  1943.   transfers between the buffer and the source/destination memory.  BUFADR and
  1944.   BUFSIZE define the conventional memory buffer.  BUFADR is a linear address.
  1945.        For fastest transfers, the memory block and the buffer should be DWORD
  1946.   aligned and should have sizes equal to an integer multiple of four.
  1947.        FPTR and FPTRMODE specify the file pointer setting to be used before
  1948.   transfers to or from the disk.  FPTRMODE specifies how FPTR is to be
  1949.   interpreted.  The following values are valid for FPTRMODE:
  1950.  
  1951.  
  1952.   FPTRMODE    FPTR Interpretation
  1953.   0           Unsigned offset from the beginning of the file
  1954.   1           Signed offset from the current file pointer
  1955.   2           Signed offset from the end of the file
  1956.   3           FPTR is ignored.  Use current file pointer (sequential mode)
  1957.  
  1958.  
  1959.  
  1960.                                         28
  1961.  
  1962.  
  1963.  
  1964.  
  1965.  
  1966.  
  1967.        CONTROL is not used in the present version of XLIB.  Set all bits in
  1968.   CONTROL to zero.
  1969.        In assembly language or C, the file control block would typically be
  1970.   defined by a structure.  In BASIC, the file control block can be defined with
  1971.   a user defined type.
  1972.        Values are transferred to and from all file routines in EAX and in the
  1973.   file control block.  All routines should be called with the linear address of
  1974.   the file control block in EAX.  All routines return with two copies of the
  1975.   error code - one in EAX and one in the condition code of the file control
  1976.   block.  A zero error code indicates successful execution.
  1977.        Since these routines perform disk operations, special precautions should
  1978.   be taken to ensure that parameters in the file control block are properly
  1979.   defined before performing calls.  In particular, one should always make sure
  1980.   that the source/destination memory block and the conventional memory buffer
  1981.   are properly defined.  A safe rule is to simply set the buffer size to zero
  1982.   because this forces XLIB to supply a buffer when opening or creating the file.
  1983.  
  1984.  
  1985.   Detailed Specifications
  1986.  
  1987.  
  1988.   XCREATE (Create File)
  1989.   Purpose:  Create and open a new file of specified name in specified directory.
  1990.   CPU Mode:  Real
  1991.   Registers at Call:  EAX = linear address of file control block.
  1992.   Control Block at Call:  FNAME = file path and name.
  1993.   Return Registers:  EAX = error code.  AX = XLIB error code.  If a DOS error
  1994.   occurred, then the high word of EAX will be set to the DOS error code.
  1995.   Control Block at Return:  CONDCODE = error code.  If CONDCODE = 0, then
  1996.   FHANDLE = file handle assigned by DOS.  If the procedure is called with
  1997.   BUFSIZE = 0, then XLIB will set BUFADR and BUFSIZE to its own internal buffer.
  1998.   Details:
  1999.      If the file already exists, then it will be truncated to zero length.
  2000.      The size and location of the internal buffer will depend upon how XLIB was
  2001.   initialized.  If DPMI is active, then the buffer will be slightly larger than
  2002.   2K; otherwise, the buffer will be slightly larger than 1K.  The linear address
  2003.   and size of the buffer may be obtained from FILEBUFADR (DWORD), and
  2004.   FILEBUFSIZE (WORD) in DSEG.
  2005.      Files created by this routine will be given both read and write access.
  2006.      This routine uses INT 21H function 3CH to create the file.
  2007.  
  2008.   XOPEN (Open File)
  2009.   Purpose:  Open existing file of specified name in specified directory.
  2010.   CPU Mode:  Real
  2011.   Registers at Call:  EAX = linear address of file control block.
  2012.   Control Block at Call:  FNAME = file path and name.
  2013.   Return Registers:  EAX = error code.  AX = XLIB error code.  If a DOS error
  2014.   occurred, then the high word of EAX will be set to the DOS error code.
  2015.   Control Block at Return:  CONDCODE = error code.  If CONDCODE = 0, then
  2016.   FHANDLE = file handle assigned by DOS.  If the procedure is called with
  2017.   BUFSIZE = 0, then XLIB will set BUFADR and BUFSIZE to its own internal buffer.
  2018.  
  2019.  
  2020.  
  2021.  
  2022.  
  2023.  
  2024.                                         29
  2025.  
  2026.  
  2027.  
  2028.  
  2029.  
  2030.  
  2031.   Details:
  2032.      The file is opened for both read and write access.
  2033.      The size and location of the internal buffer will depend upon how XLIB was
  2034.   initialized.  If DPMI is active, then the buffer will be slightly larger than
  2035.   2K; otherwise, the buffer will be slightly larger than 1K.  The linear address
  2036.   and size of the buffer may be obtained from FILEBUFADR (DWORD), and
  2037.   FILEBUFSIZE (WORD) in DSEG.
  2038.      This routine uses INT 21H function 3DH to open the file.
  2039.  
  2040.   XCLOSE (Close File)
  2041.   Purpose:  Close previously opened file.
  2042.   CPU Mode:  Real
  2043.   Registers at Call:  EAX = linear address of file control block.
  2044.   Control Block at Call:  FHANDLE = file handle.
  2045.   Return Registers:  EAX = error code.  AX = XLIB error code.  If a DOS error
  2046.   occurred, then the high word of EAX will be set to the DOS error code.
  2047.   Control Block at Return:  CONDCODE = error code.
  2048.   Details:  This routine uses INT 21H function 3EH to close the file.
  2049.  
  2050.   XSAVE (Save File)
  2051.   Purpose:  Create file with contents equal to specified memory block.
  2052.   CPU Mode:  Real
  2053.   Registers at Call:  EAX = linear address of file control block.
  2054.   Control Block at Call:  FNAME = file path and name.  BLKADR/BLKSIZE = address
  2055.   and size of memory block to provide file contents.  BUFADR/BUFSIZE = address
  2056.   and size of conventional memory buffer.
  2057.   Return Registers:  EAX = error code.  AX = XLIB error code.  If a DOS error
  2058.   occurred, then the high word of EAX will be set to the DOS error code.
  2059.   Control Block at Return:  CONDCODE = error code.
  2060.   Details:
  2061.      The file cannot already be open.  The file is both created and closed by
  2062.   this routine.
  2063.      This routine will replace any previously existing file named FNAME.
  2064.      BLKADR/BLKSIZE may define a conventional memory block provided that this
  2065.   block is not overlapped by BUFADR/BUFSIZE.
  2066.      If this routine is called with BUFSIZE = 0, then XLIB will automatically
  2067.   set BUFADR and BUFSIZE to its own internal buffer.
  2068.      This routine transfers the source memory to the file through the buffer.
  2069.   Transfers from buffer to disk are accomplished with INT 21H function 40H.
  2070.  
  2071.   XLOAD (Load File)
  2072.   Purpose:  Load file contents to specified memory block.
  2073.   CPU Mode:  Real
  2074.   Registers at Call:  EAX = linear address of file control block.
  2075.   Control Block at Call:  FNAME = file path and name.  BLKADR/BLKSIZE = address
  2076.   and size of memory block to receive file contents.  BUFADR/BUFSIZE = address
  2077.   and size of conventional memory buffer.
  2078.   Return Registers:  EAX = error code.  AX = XLIB error code.  If a DOS error
  2079.   occurred, then the high word of EAX will be set to the DOS error code.
  2080.   Control Block at Return:  CONDCODE = error code.  If CONDCODE = 0, then
  2081.   BLKSIZE = actual number of bytes transferred.
  2082.  
  2083.  
  2084.  
  2085.  
  2086.  
  2087.  
  2088.                                         30
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.   Details:
  2096.      The file cannot already be open.  The file is both opened and closed by
  2097.   this routine.
  2098.      The value of BLKSIZE as of call is interpreted as an upper limit on the
  2099.   number of bytes to transfer.  The entire file is loaded provided that it does
  2100.   not contain more than BLKSIZE bytes.
  2101.      BLKADR/BLKSIZE may define a conventional memory block provided that this
  2102.   block is not overlapped by BUFADR/BUFSIZE.
  2103.      If this routine is called with BUFSIZE = 0, then XLIB will automatically
  2104.   set BUFADR and BUFSIZE to its own internal buffer.
  2105.      This routine uses INT 21H function 3FH to transfer the disk contents to the
  2106.   buffer.  It then transfers the buffer contents to the destination memory.
  2107.  
  2108.   XWRITE (Write to File)
  2109.   Purpose:  Write specified memory block to specified location in open file.
  2110.   CPU Mode:  Real
  2111.   Registers at Call:  EAX = linear address of file control block.
  2112.   Control Block at Call:  FHANDLE = file handle.  FPTR/FPTRMODE = file pointer
  2113.   setting for beginning of transfer.  BLKADR/BLKSIZE = address and size of
  2114.   memory block to provide file contents.  BUFADR/BUFSIZE = address and size of
  2115.   conventional memory buffer.
  2116.   Return Registers:  EAX = error code.  AX = XLIB error code.  If a DOS error
  2117.   occurred, then the high word of EAX will be set to the DOS error code.
  2118.   Control Block at Return:  CONDCODE = error code.
  2119.   Details:
  2120.      The file must be opened with XOPEN or XCREATE before using this routine.
  2121.      BLKADR/BLKSIZE may define a conventional memory block provided that this
  2122.   block is not overlapped by BUFADR/BUFSIZE.
  2123.      This routine uses INT 21H function 42H to set the file pointer.  The source
  2124.   memory is then transferred through the buffer to disk.  Transfers from buffer
  2125.   to disk are accomplished with INT 21H function 40H.
  2126.      Sequential transfers should set FPTRMODE = 3 for fastest execution.
  2127.  
  2128.   XREAD (Read From File)
  2129.   Purpose:  Load specified memory block from specified location in open file.
  2130.   CPU Mode:  Real
  2131.   Registers at Call:  EAX = linear address of file control block.
  2132.   Control Block at Call:  FHANDLE = file handle.  FPTR/FPTRMODE = file pointer
  2133.   setting for beginning of transfer.  BLKADR/BLKSIZE = address and size of
  2134.   memory block to receive file contents.  BUFADR/BUFSIZE = address and size of
  2135.   conventional memory buffer.
  2136.   Return Registers:  EAX = error code.  AX = XLIB error code.  If a DOS error
  2137.   occurred, then the high word of EAX will be set to the DOS error code.
  2138.   Control Block at Return:  CONDCODE = error code.  If CONDCODE = 0, then
  2139.   BLKSIZE = actual number of bytes transferred.
  2140.   Details:
  2141.      The file must be opened with XOPEN or XCREATE before using this routine.
  2142.      BLKADR/BLKSIZE may define a conventional memory block provided that this
  2143.   block is not overlapped by BUFADR/BUFSIZE.
  2144.      This routine uses INT 21H function 42H to set the file pointer.  The file
  2145.   contents are then transferred to the destination memory through the buffer.
  2146.   The file contents are transferred to the buffer using INT 21H function 3FH.
  2147.      Sequential transfers should set FPTRMODE = 3 for fastest execution.
  2148.  
  2149.  
  2150.  
  2151.  
  2152.                                         31
  2153.  
  2154.  
  2155.  
  2156.  
  2157.  
  2158.  
  2159.   PMXCREATE (Protected Mode - Create File)
  2160.   Purpose:  Create and open a new file of specified name in specified directory.
  2161.   CPU Mode:  Protected
  2162.   Details:  This routine is the protected-mode version of XCREATE.  See XCREATE
  2163.   for details.
  2164.  
  2165.   PMXOPEN (Protected Mode - Open File)
  2166.   Purpose:  Open an existing file of specified name in specified directory.
  2167.   CPU Mode:  Protected
  2168.   Details:  This routine is the protected-mode version of XOPEN.  See XOPEN for
  2169.   details.
  2170.  
  2171.   PMXCLOSE (Protected Mode - Close File)
  2172.   Purpose:  Close previously opened file.
  2173.   CPU Mode:  Protected
  2174.   Details:  This routine is the protected-mode version of XCLOSE.  See XCLOSE
  2175.   for details.
  2176.  
  2177.   PMXSAVE (Protected Mode - Save File)
  2178.   Purpose:  Create file with contents equal to specified memory block.
  2179.   CPU Mode:  Protected
  2180.   Details:  This routine is the protected-mode version of XSAVE.  See XSAVE for
  2181.   details.
  2182.  
  2183.   PMXLOAD (Protected Mode - Load File)
  2184.   Purpose:  Load file contents to specified memory block.
  2185.   CPU Mode:  Protected
  2186.   Details:  This routine is the protected-mode version of XLOAD.  See XLOAD for
  2187.   details.
  2188.  
  2189.   PMXWRITE (Protected Mode - Write to File)
  2190.   Purpose:  Write specified memory block to specified location in open file.
  2191.   CPU Mode:  Protected
  2192.   Details:  This routine is the protected-mode version of XWRITE.  See XWRITE
  2193.   for details.
  2194.  
  2195.   PMXREAD (Protected Mode - Read From File)
  2196.   Purpose:  Load specified memory block from specified location in open file.
  2197.   CPU Mode:  Protected
  2198.   Details:  This routine is the protected-mode version of XREAD.  See XREAD for
  2199.   details.
  2200.  
  2201.  
  2202.  
  2203.  
  2204.  
  2205.  
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.  
  2212.  
  2213.  
  2214.  
  2215.  
  2216.                                         32
  2217.  
  2218.  
  2219.  
  2220.  
  2221.  
  2222.  
  2223.                              9. Descriptor Management
  2224.  
  2225.  
  2226.        All selectors in Table 1 up to DGROUPSEL are used by XLIB procedures;
  2227.   consequently, the corresponding descriptors should never be changed.  However,
  2228.   descriptors for the other selectors may be modified.  XLIB includes a
  2229.   procedure called SETDESC (set descriptor) to facilitate such modifications.  A
  2230.   second routine called PMSETDESC is the protected-mode version of SETDESC.
  2231.        Descriptors corresponding to the inline selectors should not be changed
  2232.   in programs which also use the inline mode-switch procedures.
  2233.  
  2234.  
  2235.   Detailed Specifications
  2236.  
  2237.  
  2238.   SETDESC (Set Descriptor)
  2239.   Purpose:  Change a descriptor in the local descriptor table.
  2240.   CPU Mode:  Real
  2241.   Registers at Call:  BX = selector.  EDX:EAX = the new descriptor.
  2242.   Return Registers:  EAX = error code.  AX = XLIB error code.  If DPMI is
  2243.   installed, then the high word of EAX will equal a DPMI 1.0 error code (if
  2244.   provided by host).  EDX may be returned with some modifications to the access
  2245.   rights bits.
  2246.   Details:
  2247.      The access rights bits in EDX will be edited before installation of the
  2248.   descriptor.  In particular:  The application bit will be set to indicate an
  2249.   application segment (rather than a system segment).  Reserved bits will be
  2250.   given proper settings.  The descriptor privilege level will be set to the
  2251.   appropriate value.  If the descriptor corresponds to a code segment, then the
  2252.   descriptor will also be marked as readable and nonconforming.
  2253.      Segment registers which are loaded with the old value of the descriptor
  2254.   will not necessarily be reloaded when the descriptor is changed.
  2255.  
  2256.   PMSETDESC (Protected Mode - Set Descriptor)
  2257.   Purpose:  Change a descriptor in the local descriptor table.
  2258.   CPU Mode:  Protected
  2259.   Details:  This routine is the protected-mode version of SETDESC.  See SETDESC
  2260.   for details.
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270.  
  2271.  
  2272.  
  2273.  
  2274.  
  2275.  
  2276.  
  2277.  
  2278.  
  2279.  
  2280.                                         33
  2281.  
  2282.  
  2283.  
  2284.  
  2285.  
  2286.  
  2287.                  10. Using XLIB in High-Level Language Libraries
  2288.  
  2289.  
  2290.        The following program illustrates the usage of XLIB in libraries called
  2291.   from Microsoft BASIC 7.0.  The library contains a protected-mode procedure
  2292.   which sums the elements in a single precision array created within BASIC.  The
  2293.   general methodology here is recommended for developing assembly language
  2294.   libraries.
  2295.        Since BASIC cannot call a 32-bit segment, a real-mode interface procedure
  2296.   must be placed in a 16-bit segment to receive the BASIC call and then transfer
  2297.   execution to 32-bit protected mode.  The interface procedure is call SUMARRAY
  2298.   while the 32-bit protected-mode procedure which actually sums the array
  2299.   elements is called SUMARRAY32.
  2300.        BASIC must pass certain arguments to the library procedures.  These
  2301.   include the array address and the number of elements to be summed.  These
  2302.   arguments could be passed on the stack; however, such approach proves awkward
  2303.   since the stack must be changed when entering protected mode.  Consequently,
  2304.   BASIC places all arguments in a contiguous block of memory called a "control
  2305.   block," and then passes only the address of the control block to the library.
  2306.   BASIC constructs the control block with a user-defined type.
  2307.        The first four bytes of the control block are reserved for placement of
  2308.   error codes by the library procedures.  Also, the address of the control block
  2309.   is placed in CCODEPTR so that any FPU exceptions will be signalled in the
  2310.   error code location as well.  Were an FPU exception to occur, the FPU
  2311.   interrupt handler will immediately transfer control to EXITPM which will shift
  2312.   to real-mode, restore registers, and return control to the BASIC caller.
  2313.        The library also contains a real-mode function called LINADR which may be
  2314.   called by BASIC to convert segment addresses to linear addresses.
  2315.        An example of this same program for Microsoft C 7.0 is included in
  2316.   Appendix E.  An example for Borland C is included in the files EXAMP3B.C and
  2317.   EXAMP3B.ASM.
  2318.  
  2319.  
  2320.   Example 3:  Calling Protected-Mode Libraries From BASIC
  2321.   _____________________________________________________________________________
  2322.                             +++++++++++++++++++++++++
  2323.                             + ASSEMBLY CODE LIBRARY +
  2324.                             +++++++++++++++++++++++++
  2325.  
  2326.  
  2327.   ;The following library should be combined with XLIB.LIB using the Microsoft
  2328.   ;LINK and LIB utilities.  If BASIC is to be executed from the QBX environment,
  2329.   ;then a quick library must be loaded with the environment.  See BASIC
  2330.   ;documentation for instructions.
  2331.  
  2332.  
  2333.                  .MODEL         LARGE,PASCAL
  2334.                  .386P
  2335.  
  2336.                  INCLUDE        XLIB.INC
  2337.  
  2338.  
  2339.  
  2340.  
  2341.  
  2342.  
  2343.  
  2344.                                         34
  2345.  
  2346.  
  2347.  
  2348.  
  2349.  
  2350.  
  2351.   CSEG           SEGMENT PARA PUBLIC USE16 'CODE'
  2352.                  ASSUME CS:CSEG, DS:DSEG
  2353.  
  2354.   ;Function to calculate linear address from segment address on stack.
  2355.   ;Returns linear address in DX:AX.
  2356.   LINADR         PROC FAR PUBLIC,
  2357.                  SEGADR:DWORD                  ;Segment address of variable
  2358.                  XOR            EAX,EAX        ;Clear high words
  2359.                  XOR            EDX,EDX
  2360.                  MOV            AX,WORD PTR SEGADR[0]
  2361.                  MOV            DX,WORD PTR SEGADR[2]
  2362.                  SHL            EDX,4          ;Calculate linear address
  2363.                  ADD            EDX,EAX
  2364.                  MOV            AX,DX
  2365.                  SHR            EDX,16         ;Return linear address in DX:AX
  2366.                  RET
  2367.   LINADR         ENDP
  2368.  
  2369.   ;Structure defining control block for SUMARRAY.
  2370.   ARRAYDATA      STRUCT
  2371.     CONDCODE     DWORD          0              ;Condition code
  2372.     N            DWORD          0              ;Number of elements to sum
  2373.     ADDRESS      DWORD          0              ;Address of first element
  2374.     SUM          DWORD          0              ;Sum of array elements
  2375.   ARRAYDATA      ENDS
  2376.  
  2377.   ;Real-mode interface to SUMARRAY32.  Segment address of control block having
  2378.   ;structure ARRAYDATA should be on the stack.
  2379.   SUMARRAY       PROC FAR PUBLIC,
  2380.                  CBSEGADR:DWORD                ;Control block segment address
  2381.                  PUSH           DS
  2382.                  PUSHW          DSEG
  2383.                  POP            DS
  2384.                  XOR            EAX,EAX        ;Clear high words
  2385.                  XOR            EDX,EDX
  2386.                  MOV            AX,WORD PTR CBSEGADR[2]
  2387.                  MOV            DX,WORD PTR CBSEGADR[0]
  2388.                  SHL            EAX,4          ;Calculate linear address
  2389.                  ADD            EAX,EDX
  2390.                  MOV            CCODEPTR,EAX   ;Reset condition code address
  2391.                  POP            DS             ;Pop calling DS
  2392.                  PUSHD          OFFSET SUMARRAY32
  2393.                  CALL           ENTERPM        ;Execute SUMARRAY32 in protected
  2394.                  RET
  2395.   SUMARRAY       ENDP
  2396.  
  2397.   CSEG           ENDS
  2398.  
  2399.  
  2400.  
  2401.  
  2402.  
  2403.  
  2404.  
  2405.  
  2406.  
  2407.  
  2408.                                         35
  2409.  
  2410.  
  2411.  
  2412.  
  2413.  
  2414.  
  2415.   TSEG           SEGMENT PARA PUBLIC USE32 'CODE'
  2416.                  ASSUME CS:TSEG, SS:TSEG, DS:TSEG, ES:TSEG, FS:DSEG, GS:DGROUP
  2417.  
  2418.   ;Sum the elements of a single precision array.  Array parameters are stored
  2419.   ;in a control block having structure of ARRAYDATA.  The linear address of the
  2420.   ;control block is stored at CCODEPTR.  An error code of -1 is returned in the
  2421.   ;condition code of the control block if the number of array elements is zero.
  2422.   ;XLIB places an error code in the control block if an FPU exception occurs
  2423.   ;while calculating the sum.  This error code will have the FPU status word in
  2424.   ;the high word and the XLIB FPU error code in the low word.  Observe that this
  2425.   ;routine will be called with DS = FLATDSEL (flat-model data descriptor) and
  2426.   ;FS = DSEGSEL (DSEG data descriptor).
  2427.   SUMARRAY32     PROC NEAR
  2428.                  MOV            EBX,FS:CCODEPTR               ;Get control block
  2429.                  MOV            EDX,ARRAYDATA.ADDRESS[EBX]    ;Get array address
  2430.                  MOV            ESI,ARRAYDATA.N[EBX]          ;Get N
  2431.                  SUB            ESI,1
  2432.                  JB             NODATA                        ;Error:  N = 0
  2433.                  FLDZ                                         ;Initialize sum
  2434.   SUMLOOP:       FADD           DWORD PTR [EDX+4*ESI]
  2435.                  SUB            ESI,1
  2436.                  JAE            SUMLOOP
  2437.                  FSTP           ARRAYDATA.SUM[EBX]            ;Save sum
  2438.                  RET
  2439.   NODATA:        MOV            ARRAYDATA.CONDCODE[EBX],-1    ;Record error code
  2440.                  RET
  2441.   SUMARRAY32     ENDP
  2442.  
  2443.   TSEG           ENDS
  2444.                  END
  2445.  
  2446.  
  2447.                               +++++++++++++++++++++
  2448.                               + BASIC MAIN MODULE +
  2449.                               +++++++++++++++++++++
  2450.  
  2451.  
  2452.   'The following Microsoft BASIC 7.0 program should be linked with the above
  2453.   'library.  The BASIC program first initializes XLIB.  Next, it creates a
  2454.   'single precision array.  A control block for SUMARRAY is then constructed
  2455.   'and the call to SUMARRAY is executed.  Finally, the condition code in the
  2456.   'control block is inspected and results are printed.
  2457.  
  2458.   DEFINT A-Z
  2459.  
  2460.   'Declare XLIB procedures
  2461.   DECLARE FUNCTION XLIBMEMREQ& ()
  2462.   DECLARE FUNCTION INITXLIB& ()
  2463.   DECLARE FUNCTION XLIBCONFIG% ()
  2464.  
  2465.   'Declare procedures in the library linked with XLIB
  2466.   DECLARE FUNCTION LINADR& (SEG VARIABLE AS ANY)
  2467.   DECLARE SUB SUMARRAY (SEG VARIABLE AS ANY)
  2468.  
  2469.  
  2470.  
  2471.  
  2472.                                         36
  2473.  
  2474.  
  2475.  
  2476.  
  2477.  
  2478.  
  2479.   'Structure for the control block
  2480.   TYPE ARRAYDATA
  2481.     CONDCODE AS LONG      'Location to receive any error codes
  2482.     N AS LONG             'Number of elements to be summed
  2483.     ADDRESS AS LONG       'Linear address of the array
  2484.     SUM AS SINGLE         'Location for array sum
  2485.   END TYPE
  2486.  
  2487.   'Check XLIBCONFIG to see if XLIB has already been initialized.  If not then
  2488.   'call XLIBMEMREQ to find amount of conventional memory needed by XLIB and
  2489.   'release at least this amount with the BASIC SETMEM function.  XLIBMEMREQ
  2490.   'returns with sign bit of DX set if an error occurred.  The error is then
  2491.   'identified by AX.  XLIB will not be terminated upon completion of this
  2492.   'program in the Microsoft QBX environment; therefore, initialization is
  2493.   'required only once within the environment.
  2494.   IF XLIBCONFIG = 0 THEN
  2495.     TEMP& = XLIBMEMREQ
  2496.     IF TEMP& >= 0& THEN
  2497.       IF TEMP& > 0 THEN TEMP& = SETMEM(-TEMP& - 16&)
  2498.       TEMP& = INITXLIB                 'INITXLIB error code returned in TEMP&
  2499.     ELSE
  2500.       TEMP& = TEMP& AND &H7FFFFFFF     'Mask sign bit to leave error code only
  2501.     END IF
  2502.     IF TEMP& THEN
  2503.       PRINT "Library initialization error:  "; HEX$(TEMP&)
  2504.       END
  2505.     END IF
  2506.   END IF
  2507.  
  2508.   DIM A(100) AS SINGLE
  2509.   DIM AD AS ARRAYDATA
  2510.  
  2511.   FOR I = 0 TO 100            'Assign numbers to array
  2512.     A(I) = I
  2513.   NEXT I
  2514.  
  2515.   AD.CONDCODE = 0&            'Clear the error code
  2516.   AD.N = 50&                  'Sum first 50 elements
  2517.   AD.ADDRESS = LINADR(A(0))   'Calculate and record linear address of A(0)
  2518.  
  2519.   CALL SUMARRAY(AD)
  2520.  
  2521.   IF AD.CONDCODE THEN
  2522.     PRINT "Error: ";HEX$(AD.CONDCODE)
  2523.   ELSE
  2524.     PRINT "Sum: ";AD.SUM      'Should equal 1225
  2525.   ENDIF
  2526.  
  2527.   END
  2528.   _____________________________________________________________________________
  2529.  
  2530.  
  2531.  
  2532.  
  2533.  
  2534.  
  2535.  
  2536.                                         37
  2537.  
  2538.  
  2539.  
  2540.  
  2541.  
  2542.  
  2543.                    Appendix A: Description of XLIB Public Data
  2544.  
  2545.  
  2546.        The following is a summary of most public symbols for XLIB data.  These
  2547.   symbols pertain to segment DSEG except where otherwise noted.  This summary
  2548.   excludes many of the symbols presented in tables one through four.  All XLIB
  2549.   symbols conform to the PASCAL naming convention.
  2550.  
  2551.   Symbol:  CALL32PTR (CALL32 Pointer)
  2552.   Symbol Type:  DWORD
  2553.   Default Setting:  Far 16-bit protected-mode address of CALL32 procedure
  2554.   Description:  This location is a pointer to the CALL32 procedure and is
  2555.   included to facilitate intersegment calls.  The contents of the location
  2556.   should not be changed.
  2557.  
  2558.   Symbols:  CCODEPTR/CCODE (Condition Code Pointer/Condition Code)
  2559.   Symbol Types:  DWORD/DWORD
  2560.   Default Settings:  CCODEPTR = linear address of CCODE.  CCODE = 0.
  2561.   Descriptions:  XLIB interrupt handlers will place flags in the condition code
  2562.   to signal the occurrence of the interrupt.  Flags are placed for FPU
  2563.   exceptions and hot key presses.  CCODEPTR initially contains the linear
  2564.   address of CCODE.  CCODEPTR may be changed by the user, but must point to a
  2565.   DWORD in conventional memory.  The user is responsible for initializing the
  2566.   condition code.
  2567.  
  2568.   Symbol:  CSDSEGSEL (Code Segment Copy of DSEGSEL)
  2569.   Symbol Type:  WORD
  2570.   Default Setting:  Varies with operating environment
  2571.   Description:  This is a WORD in TSEG containing the value of the DSEG
  2572.   selector.  Since XLIB selector values are not constant, they must be read from
  2573.   memory locations.  Such locations are placed in segment DSEG (see Table 1);
  2574.   however, one must know the DSEG selector to read these locations.  Therefore,
  2575.   a copy of the DSEG selector is placed in the code segment where it can always
  2576.   be found.
  2577.  
  2578.   Symbols:  CSEGVAL, TSEGVAL, DSEGVAL, DGROUPVAL (Segment Values)
  2579.   Symbol Types:  WORD
  2580.   Default Settings:  CSEG, TSEG, DSEG, DGROUP
  2581.   Descriptions:  These are memory locations initialized to the respective
  2582.   segment values.  Code in TSEG should not contain segment constants since DOS
  2583.   may not be able to handle them in relocation edits.  Read these locations to
  2584.   get segment values.  User segments should be handled the same way.  These
  2585.   locations should not be changed.
  2586.  
  2587.   Symbols:  FILEBUFADR/FILEBUFSIZE (File Buffer Specifications)
  2588.   Symbol Types:  DWORD/WORD
  2589.   Default Settings:  Varies with operating environment
  2590.   Descriptions:  FILEBUFADR contains the linear address of the internal file
  2591.   buffer in XLIB.  FILEBUFSIZE contains the size of the buffer in bytes.  This
  2592.   buffer is used only by the file management routines.  The size and location of
  2593.   the buffer will depend upon the operating environment.  If DPMI is active,
  2594.   then the buffer will be slightly larger than 2K; it is otherwise slightly
  2595.   larger than 1K.  These location should be read only after initialization.
  2596.  
  2597.  
  2598.  
  2599.  
  2600.                                         38
  2601.  
  2602.  
  2603.  
  2604.  
  2605.  
  2606.  
  2607.   Symbol:  FPUCW (Floating Point Unit Control Word)
  2608.   Symbol Type:  WORD
  2609.   Default Setting:  0332H
  2610.   Description:  FPUCW is optionally loaded to the FPU control word by CALLPM and
  2611.   ENTERPM.  The default sets rounding control to nearest, precision control to
  2612.   64 bits, and unmasks exceptions for overflow, zero divide, and invalid
  2613.   operations.  Exceptions for underflow, precision, and denormalized operations
  2614.   are masked, and are therefore handled internally by the FPU.  Set bit 2 of
  2615.   OFLAGS to enable FPU save/restore and load of FPUCW.
  2616.  
  2617.   Symbol:  HOTKEY (Hot Key)
  2618.   Symbol Type:  WORD
  2619.   Default Setting:  0H
  2620.   Description:  HOTKEY specifies the hot key for the keyboard interrupt handler.
  2621.   The low byte of HOTKEY specifies the scan code for the key.  The upper byte
  2622.   specifies the state of the shift keys.  Bit 8 specifies SHIFT; bit 9 specifies
  2623.   CTLR, and bit 10 specifies ALT.  Set bits mean that the designated key must be
  2624.   pressed.  All other bits are ignored.  When the hot key is pressed, the XLIB
  2625.   keyboard interrupt handler will record the hot key flag at the DWORD whose
  2626.   linear address is stored at CCODEPTR.  The default setting for HOTKEY is 0.
  2627.   This setting effectively disables hot key detection since no key has a zero
  2628.   scan code.
  2629.  
  2630.   Symbol:  IFLAGS (Initialization Flags)
  2631.   Symbol Type:  WORD
  2632.   Default Setting:  0200
  2633.   Description:  IFLAGS is used by INITXLIB to control the initialization
  2634.   process.  Bit 0 of IFLAGS determines DPMI/VCPI priority in the event that both
  2635.   interfaces are present.  If this bit is clear then DPMI will be installed in
  2636.   such cases.  The upper byte of IFLAGS determines the strategy to be used by
  2637.   INITXLIB if conventional memory is to be allocated.  The possible strategies
  2638.   are presented in Table 2.  The default causes XLIB to allocate from the
  2639.   highest available address in conventional memory.
  2640.  
  2641.   Symbol:  INLINERMPTR (INLINERM Pointer)
  2642.   Symbol Type:  DWORD
  2643.   Default Setting:  Far 16-bit protected-mode address of INLINERM procedure
  2644.   Description:  This location is a pointer to the INLINERM procedure and is
  2645.   included to facilitate intersegment calls.  The contents of the location
  2646.   should not be changed.
  2647.  
  2648.   Symbols:  IRQ0INTNO/IRQ8INTNO (IRQ X Interrupt Number)
  2649.   Symbol Types:  BYTE/BYTE
  2650.   Default Settings:  Varies with operating environment
  2651.   Descriptions:  Specifies the interrupt number assigned to IRQ X.  IRQs 0
  2652.   through 7 and IRQs 8 through 15 are assigned to contiguous interrupt numbers.
  2653.   These locations are valid only after call to INITXLIB.  Typically, IRQ 0 is
  2654.   assigned to interrupt 8, and IRQ 8 is assigned to interrupt 70H; however,
  2655.   these assignments may have been changed by system software.
  2656.  
  2657.  
  2658.  
  2659.  
  2660.  
  2661.  
  2662.  
  2663.  
  2664.                                         39
  2665.  
  2666.  
  2667.  
  2668.  
  2669.  
  2670.  
  2671.   Symbol:  OFLAGS (Operation Flags)
  2672.   Symbol Type:  WORD
  2673.   Default Setting:  Varies with operating environment
  2674.   Description:  OFLAGS controls post-initialization operation of XLIB.
  2675.      Setting bit 0 enables XLIB hardware interrupt handlers.  These handlers
  2676.   will continue to receive interrupts but will always cascade them when the bit
  2677.   is clear.  XLIB sets this bit only at calls to CALLPM and ENTERPM and then
  2678.   clears the bit upon return.  When the bit is clear, hot key detection is
  2679.   disabled, and the XLIB FPU interrupt handler is disabled.
  2680.      Setting bit 1 causes all FPU interrupts to be cascaded to the inherited
  2681.   real-mode interrupt handler.  This bit is initialized by INITXLIB.  It is set
  2682.   if no FPU is present; it is otherwise cleared.
  2683.      Setting bit 2 enables FPU save/restore in CALLPM and ENTERPM.  Setting this
  2684.   bit also causes load of FPUCW to the FPU control word.  The bit is clear by
  2685.   default.
  2686.  
  2687.   Symbol:  PAGESIZE (Page Size)
  2688.   Symbol Type:  DWORD
  2689.   Default Setting:  Varies with operating environment
  2690.   Description:  This memory location contains the minimum unit (in bytes) for
  2691.   extended memory allocation.  PAGESIZE is initialized by INITXLIB.  It will
  2692.   contain 4096 for VCPI, 1024 for XMS, and 16 for clean configurations.  Values
  2693.   can vary under DPMI but will typically equal 4096.  Extended memory requests
  2694.   are rounded up to the nearest integer multiple of PAGESIZE.  Extended memory
  2695.   blocks will be PAGESIZE aligned.
  2696.  
  2697.   Symbols:  PMDS, PMES, PMFS, PMGS (Protected-Mode Segments)
  2698.   Symbol Types:  WORD
  2699.   Default Settings:  FLATDSEL, TSEGDSEL, DSEGSEL, DGROUPSEL
  2700.   Descriptions:  These memory locations are loaded to data segment registers by
  2701.   CALLPM and ENTERPM before transferring control to the protected-mode target.
  2702.   These locations are respectively loaded to DS, ES, FS, and GS.  The contents
  2703.   of these locations may be changed to any legal selectors after the call to
  2704.   INITXLIB.
  2705.  
  2706.   Symbols:  RMDS, RMES (Real-Mode Segments)
  2707.   Symbol Types:  WORD
  2708.   Default Settings:  DGROUP, DSEG
  2709.   Descriptions:  These memory locations are loaded to data segment registers by
  2710.   CALLRM before transferring control to the real-mode target.  These locations
  2711.   are respectively loaded to DS and ES.  The contents of these locations may be
  2712.   changed if desired.
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.                                         40
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.                            Appendix B: XLIB Error Codes
  2736.  
  2737.  
  2738.        XLIB error codes are always returned in AX.  In many cases, the high word
  2739.   of EAX will be returned with specific information about the error, such as
  2740.   XMS, DPMI, or DOS error codes.
  2741.        Although error codes are not provided in the DPMI .9 specification, many
  2742.   DPMI .9 hosts do return DPMI 1.0 error codes.  DPMI 1.0 error codes may in
  2743.   fact be DOS error codes returned to the DPMI host by DOS.  If the sign bit
  2744.   (bit 15) of the error code is clear, then the error code was issued by DOS.
  2745.  
  2746.  
  2747.   Condition Code Flags
  2748.   01H     FPU exception
  2749.   02H     Hot key pressed
  2750.  
  2751.   General Errors
  2752.   10H     Illegal address
  2753.   11H     Unable to identify operating environment
  2754.   12H     DOS memory allocation failure
  2755.   13H     DOS memory release error
  2756.   14H     Failed to enable A20
  2757.   15H     Insufficient logical address space
  2758.   16H     Insufficient number of extended memory block handles
  2759.   17H     Bad extended memory block handle
  2760.   18H     Bad selector
  2761.   19H     Unable to create file
  2762.   1AH     Unable to open file
  2763.   1BH     Unable to read file
  2764.   1CH     Unable to write file
  2765.   1DH     Unable to set file pointer
  2766.   1EH     Unable to close file
  2767.   1FH     Disk full
  2768.  
  2769.   Errors Occurring Under DPMI (See Appendix C for codes returned by DPMI)
  2770.   20H     Protected mode initialization failure
  2771.   21H     Descriptor allocation error
  2772.   22H     Descriptor installation error
  2773.   23H     Unable to switch protected mode interrupt vector
  2774.   24H     Insufficient extended memory error
  2775.   25H     Extended memory allocation error
  2776.   26H     Extended memory release error
  2777.   27H     DPMI DOS memory allocation error
  2778.   28H     DPMI DOS memory release error
  2779.   29H     Unable to set descriptor base address
  2780.   2AH     DPMI physical address mapping error
  2781.  
  2782.   Errors Occurring Under XMS (See Appendix D for codes returned by XMS)
  2783.   30H     Unable to measure available extended memory
  2784.   31H     Insufficient extended memory error
  2785.   32H     Extended memory allocation error
  2786.   33H     Unable to lock extended memory
  2787.   34H     Unable to unlock extended memory
  2788.   35H     Extended memory release error
  2789.  
  2790.  
  2791.  
  2792.                                         41
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.   Errors Occurring Under VCPI
  2800.   40H     Error in determining protected mode entry point
  2801.   41H     Unable to determine physical address of DOS memory page
  2802.   42H     Unable to determine hardware interrupt mappings
  2803.   43H     Insufficient extended memory error
  2804.   44H     Unable to determine number of free extended memory pages
  2805.   45H     Extended memory allocation error
  2806.   46H     Extended memory release error
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812.  
  2813.  
  2814.  
  2815.  
  2816.  
  2817.  
  2818.  
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.  
  2827.  
  2828.  
  2829.  
  2830.  
  2831.  
  2832.  
  2833.  
  2834.  
  2835.  
  2836.  
  2837.  
  2838.  
  2839.  
  2840.  
  2841.  
  2842.  
  2843.  
  2844.  
  2845.  
  2846.  
  2847.  
  2848.  
  2849.  
  2850.  
  2851.  
  2852.  
  2853.  
  2854.  
  2855.  
  2856.                                         42
  2857.  
  2858.  
  2859.  
  2860.  
  2861.  
  2862.  
  2863.                          Appendix C: DPMI 1.0 Error Codes
  2864.  
  2865.  
  2866.        DPMI 1.0 error codes may in fact be DOS error codes returned to the DPMI
  2867.   host by DOS.  If the sign bit (bit 15) of the error code is clear, then the
  2868.   error code was issued by DOS.
  2869.  
  2870.  
  2871.   Number   Explanation
  2872.   8001H    Unsupported function
  2873.   8002H    Invalid state for requested operation
  2874.   8003H    System integrity would be endangered
  2875.   8004H    Deadlock situation detected by host
  2876.   8005H    Serialization request cancelled
  2877.   8010H    Resource unavailable
  2878.   8011H    Host unable to allocate descriptor
  2879.   8012H    Linear memory unavailable
  2880.   8013H    Physical memory unavailable
  2881.   8014H    Backing store unavailable
  2882.   8015H    Callback specifications cannot be allocated
  2883.   8016H    Cannot allocate handle
  2884.   8017H    Lock count limits exceeded
  2885.   8018H    Resource owned exclusively by another client
  2886.   8019H    Resource already shared by another client
  2887.   8021H    Invalid value
  2888.   8022H    Invalid selector
  2889.   8023H    Invalid handle
  2890.   8024H    Invalid callback
  2891.   8025H    Invalid linear address
  2892.   8026H    Request not supported by hardware
  2893.  
  2894.  
  2895.  
  2896.  
  2897.  
  2898.  
  2899.  
  2900.  
  2901.  
  2902.  
  2903.  
  2904.  
  2905.  
  2906.  
  2907.  
  2908.  
  2909.  
  2910.  
  2911.  
  2912.  
  2913.  
  2914.  
  2915.  
  2916.  
  2917.  
  2918.  
  2919.  
  2920.                                         43
  2921.  
  2922.  
  2923.  
  2924.  
  2925.  
  2926.  
  2927.                            Appendix D: XMS Error Codes
  2928.  
  2929.  
  2930.   Number   Explanation
  2931.   80H      Function not implemented
  2932.   81H      VDISK was detected
  2933.   82H      An A20 error occurred
  2934.   8EH      General driver error
  2935.   8FH      Unrecoverable driver error
  2936.   90H      HMA does not exist
  2937.   91H      HMA is already in use
  2938.   92H      Attempt to allocate less than HMAMIN of HMA
  2939.   93H      HMA is not allocated
  2940.   94H      A20 is still enabled
  2941.   A0H      All extended memory is allocated
  2942.   A1H      All available handles are allocated
  2943.   A2H      Invalid handle
  2944.   A3H      Source handle is invalid
  2945.   A4H      Source offset is invalid
  2946.   A5H      Destination handle is invalid
  2947.   A6H      Destination offset is invalid
  2948.   A7H      Length is invalid
  2949.   A8H      Move has an invalid overlap
  2950.   A9H      Parity error
  2951.   AAH      Block is not locked
  2952.   ABH      Block is locked
  2953.   ACH      Block lock count overflow
  2954.   ADH      Lock failed
  2955.   B0H      Only a smaller upper memory block (UMB) is available
  2956.   B1H      No UMB's are available
  2957.   B2H      UMB segment number is invalid
  2958.  
  2959.  
  2960.  
  2961.  
  2962.  
  2963.  
  2964.  
  2965.  
  2966.  
  2967.  
  2968.  
  2969.  
  2970.  
  2971.  
  2972.  
  2973.  
  2974.  
  2975.  
  2976.  
  2977.  
  2978.  
  2979.  
  2980.  
  2981.  
  2982.  
  2983.  
  2984.                                         44
  2985.  
  2986.  
  2987.  
  2988.  
  2989.  
  2990.  
  2991.                Appendix E: Calling Protected-Mode Libraries From C
  2992.  
  2993.  
  2994.        This appendix contains a C version of the BASIC program presented in
  2995.   Example 3.  Microsoft C version 7.0 is used to create a float array.  C then
  2996.   calls a protected-mode assembly language procedure in a library to sum the
  2997.   elements of the array.  The assembly language library in Example 3 will work
  2998.   here with no modification.  C calls a real-mode procedure called SUMARRAY.
  2999.   This procedure then transfers control to a 32-bit protected-mode procedure
  3000.   called SUMARRAY32.  The latter procedure performs the actual calculations.
  3001.        Parameters defining the array are placed in a contiguous block of memory
  3002.   defined by a C structure.  C passes the address of this structure to the
  3003.   library.  The first four bytes in the structure are reserved for error codes.
  3004.   The linear address of the structure is placed in CCODEPTR so that any FPU
  3005.   exceptions will be recorded by the FPU interrupt handler in the error code
  3006.   location.  The SUMARRAY32 procedure will also record an error if the parameter
  3007.   defining the number of elements to be summed is zero.
  3008.        The C code is somewhat simpler than the corresponding BASIC code because
  3009.   conventional memory does not have to be released prior to calling INITXLIB.
  3010.   This follows because C does not claim all DOS memory as does BASIC.
  3011.        C is more powerful than BASIC in that it can access data under external
  3012.   symbols whereas BASIC cannot.  Access to XLIB public data is made possible in
  3013.   C by including the header file called XLIB.H.  This file makes all XLIB public
  3014.   data and public real-mode procedures visible to C.  It also contains
  3015.   declarations which adapt the PASCAL conventions of XLIB.
  3016.        A Borland version of this program and of the accompanying library may be
  3017.   found in the files EXAMP3B.C and EXAMP3B.ASM.
  3018.  
  3019.  
  3020.  
  3021.  
  3022.  
  3023.  
  3024.  
  3025.  
  3026.  
  3027.  
  3028.  
  3029.  
  3030.  
  3031.  
  3032.  
  3033.  
  3034.  
  3035.  
  3036.  
  3037.  
  3038.  
  3039.  
  3040.  
  3041.  
  3042.  
  3043.  
  3044.  
  3045.  
  3046.  
  3047.  
  3048.                                         45
  3049.  
  3050.  
  3051.  
  3052.  
  3053.  
  3054.  
  3055.   _____________________________________________________________________________
  3056.   /*The following Microsoft C 7.0 program should be linked with the assembly
  3057.   language library in Example 3.  Combine the library with XLIB.LIB using the
  3058.   Microsoft LIB utility.  The C program first initializes XLIB.  Next, it
  3059.   creates a float array.  A control block for SUMARRAY is then constructed
  3060.   and the call to SUMARRAY is executed.  Finally, the condition code in the
  3061.   control block is inspected and results are printed.*/
  3062.  
  3063.   #include <stdio.h>
  3064.   #include <xlib.h>
  3065.  
  3066.   extern long __far __pascal LINADR(void __far *ptr);
  3067.   extern void __far __pascal SUMARRAY(void __far *ptr);
  3068.  
  3069.   struct arraydata            /*Structure for passing arguments to SUMARRAY*/
  3070.   {
  3071.     long condcode;
  3072.     long n;
  3073.     long address;
  3074.     float sum;
  3075.   } ad;
  3076.  
  3077.   main()
  3078.   {
  3079.     int i;
  3080.     long temp;
  3081.     float a[101];
  3082.     temp = INITXLIB();        /*Initialize XLIB*/
  3083.     if (temp != 0)            /*See if an error occurred*/
  3084.     {
  3085.       printf("Initialization Error:  %lX\n",temp);
  3086.       return 0;
  3087.     }
  3088.  
  3089.     for(i = 0; i <= 100; i++)   /*Initialize a[]*/
  3090.       a[i] = i;
  3091.  
  3092.     ad.condcode = 0;            /*Initialize the condition code*/
  3093.     ad.n = 50;                  /*Will sum the first 50 elements in a[]*/
  3094.     ad.address = LINADR(a);     /*Compute and record linear address of a[]*/
  3095.  
  3096.     SUMARRAY(&ad);              /*Sum the array elements*/
  3097.     if (ad.condcode != 0)       /*See if an FPU error occurred*/
  3098.     {
  3099.       printf("Error:  %lX\n",ad.condcode);
  3100.       return 0;
  3101.     }
  3102.     printf("Sum:  %f\n",ad.sum);   /*The sum should be 1225*/
  3103.   }
  3104.   _____________________________________________________________________________
  3105.  
  3106.  
  3107.  
  3108.  
  3109.  
  3110.  
  3111.  
  3112.                                         46
  3113.  
  3114.  
  3115.  
  3116.  
  3117.  
  3118.  
  3119.                      Appendix F: Reporting Problems With XLIB
  3120.  
  3121.  
  3122.        All efforts to isolate and report problems with XLIB will be appreciated.
  3123.   The following steps will greatly facilitate bug-tracking:
  3124.  
  3125.   1) Ensure that your own program always checks the error codes returned by XLIB
  3126.   procedures.  These codes will likely resolve the problem.  If not, then make
  3127.   note of the code.
  3128.  
  3129.   2) Attempt to execute your program under DPMI, VCPI, and in the absence of
  3130.   both.  If the problem relates to memory management, then also attempt to
  3131.   execute your program in the presence of XMS but in the absence of DPMI and
  3132.   VCPI, then attempt to execute in the absence of all three interfaces.  It will
  3133.   generally be found that the problem occurs only under a specific interface.
  3134.   If so, then note the interface under which the problem occurs.
  3135.  
  3136.   3) If the problem occurs only under one interface, then attempt to execute
  3137.   your program under different implementations of the interface.  For example, a
  3138.   DPMI host is contained in Windows 3.1, 386MAX, QDPMI, and OS/2 2.x.  Try
  3139.   executing your program under each host and make note of the results.  Problems
  3140.   occurring only under one host are generally indicative of bugs in the host
  3141.   rather than XLIB.
  3142.  
  3143.   4) Try different options on your compiler, assembler, and linker.  It is
  3144.   sometimes the case that code is not processed properly under some options.
  3145.  
  3146.   5) Report problems to:
  3147.  
  3148.   Dr. David Pyles
  3149.   TechniLib Company
  3150.   P.O. Box 6818
  3151.   Jackson, Ms. 39282
  3152.   (601) 372-7433
  3153.  
  3154.  
  3155.  
  3156.  
  3157.  
  3158.  
  3159.  
  3160.  
  3161.  
  3162.  
  3163.  
  3164.  
  3165.  
  3166.  
  3167.  
  3168.  
  3169.  
  3170.  
  3171.  
  3172.  
  3173.  
  3174.  
  3175.  
  3176.                                         47
  3177.  
  3178.  
  3179.  
  3180.  
  3181.  
  3182.  
  3183.                  Appendix G: The SWITCHPM and SWITCHRM Procedures
  3184.  
  3185.  
  3186.        SWITCHPM and SWITCHRM are the primitive mode-switch routines used by
  3187.   nearly all XLIB procedures requiring execution in both real and protected
  3188.   modes.  They are made public for users who need to perform mode switching
  3189.   tasks not provided by XLIB.  These routines do not conform to the general
  3190.   conventions followed by other XLIB procedures; consequently, they are
  3191.   presented in an appendix.
  3192.        There are special situations in which CALLPM and ENTERPM may not be
  3193.   suitable for performing mode switches.  For example, suppose one has a
  3194.   protected-mode hardware interrupt handler that is intended to service
  3195.   interrupts occurring in both real and protected modes.  Unless DPMI is
  3196.   installed, the user will have to write a second handler to deflect real-mode
  3197.   interrupts to the protected-mode handler.  CALLPM and ENTERPM could not be
  3198.   used in the event that the interrupt occurred in a real-mode procedure called
  3199.   from protected mode will CALLRM.  This follows because CALLPM and ENTERPM are
  3200.   not reentrant.  Instead, the user must perform the mode switches either with
  3201.   DEFLECTPM or with SWITCHPM and SWITCHRM.  The user might also wish to use
  3202.   SWITCHPM and SWITCHRM to avoid the overhead of CALLPM and ENTERPM.  SWITCHPM
  3203.   and SWITCHRM perform mode switches in minimum CPU time.
  3204.        Both SWITCHPM and SWITCHRM are near procedures in CSEG; therefore, they
  3205.   must be called from this segment.  SWITCHPM returns to the caller in 16-bit
  3206.   protected mode.  SWITCHRM returns to the caller in real mode.  Both procedures
  3207.   must be called with a stack in DSEG.  Do not use XLIB stacks for this purpose.
  3208.        SWITCHPM returns with CS = CSEGSEL and with all other segments equal to
  3209.   DSEGSEL.  All other registers, except the status flags, are preserved.
  3210.        SWITCHRM returns with CS = CSEG and with SS, DS, and ES set to DSEG.  FS
  3211.   and GS are undefined.  All other registers, except the status flags, are
  3212.   preserved.
  3213.  
  3214.  
  3215.  
  3216.  
  3217.  
  3218.  
  3219.  
  3220.  
  3221.  
  3222.  
  3223.  
  3224.  
  3225.  
  3226.  
  3227.  
  3228.  
  3229.  
  3230.  
  3231.  
  3232.  
  3233.  
  3234.  
  3235.  
  3236.  
  3237.  
  3238.  
  3239.  
  3240.                                         48