home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / PROG / XLIB.ZIP / XLIB.DOC < prev    next >
Encoding:
Text File  |  1993-08-20  |  79.7 KB  |  2,278 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.  
  31.                              XLIB PROGRAMMER'S MANUAL
  32.                                    VERSION 1.0
  33.  
  34.                               (DOS Extender Library)
  35.  
  36.                                 TechniLib Company
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.                     Copyright 1993, by TechniLib (TM) Company
  61.                                All Rights Reserved
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.                           TERMS OF USE AND DISTRIBUTION
  69.  
  70.  
  71.        XLIB is a shareware product; therefore, unregistered copies of XLIB are
  72.   made available free of charge so that potential purchasers will have the
  73.   opportunity to examine and test the software before committing payment.
  74.   Distribution of unregistered copies of XLIB to other potential users is also
  75.   permitted and appreciated.  However, usage and distribution of XLIB must
  76.   conform to the following conditions.  In the following statement, the term
  77.   "commercial distribution," includes shareware distribution.
  78.  
  79.   1) XLIB and accompanying software must be distributed together in copies of
  80.   the original archive provided by TechniLib.  Neither the archive nor
  81.   individual files therein may be modified.
  82.  
  83.   2) The XLIB archive may be distributed in combination with other shareware
  84.   products; however, the XLIB archive may not be distributed with other
  85.   commercially distributed software without written consent of TechniLib.
  86.  
  87.   3) Copies of XLIB which have been used to develop software for commercial
  88.   distribution must be registered before such software is marketed.  Copies of
  89.   XLIB which have been used to develop noncommercial software must be registered
  90.   if such software is to be regularly used either by the developer or others.
  91.  
  92.   4) Commercially distributed software must embed XLIB procedures in the
  93.   software code.  Files contained in the XLIB archive may not be placed in the
  94.   distribution media.
  95.  
  96.   5) XLIB is designed to offer a set of services to other executable code.  XLIB
  97.   may not be used to develop software for commercial distribution which will
  98.   essentially offer any of these same services to other executable code.
  99.   Exceptions to this condition require written consent of TechniLib.
  100.  
  101.   6) Rights afforded by registering a single copy of XLIB pertain only to a
  102.   single computer.
  103.  
  104.   7) XLIB may be registered for a fee of $45.00 per copy.  Accompany payment
  105.   with the registration form included in the XLIB archive.  Registrants will be
  106.   entitled to the most recent version of the XLIB archive.
  107.  
  108.  
  109.                               DISCLAIMER OF WARRANTY
  110.  
  111.  
  112.        XLIB AND ALL ACCOMPANYING SOFTWARE AND LITERATURE ARE DISTRIBUTED WITH
  113.   THE EXCLUSION OF ANY AND ALL IMPLIED WARRANTIES, AND WITH THE EXCLUSION OF
  114.   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  TechniLib
  115.   SHALL HAVE NO LIABILITY FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  116.   RESULTING FROM THE USE OF XLIB OR ACCOMPANYING MATERIALS.  The user assumes
  117.   the entire risk of using this software.
  118.  
  119.  
  120.                     Copyright 1993, by TechniLib (TM) Company
  121.                                All Rights Reserved
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.                                 TABLE OF CONTENTS
  129.  
  130.  
  131.   CHAPTERS
  132.                                                                      Page
  133.   1. Introduction                                                       1
  134.   2. XLIB Conventions and Structure                                     3
  135.   3. Mode Switching                                                     5
  136.   4. Interrupt Management                                               7
  137.   5. Memory Management                                                 10
  138.   6. XLIB Initialization                                               11
  139.   7. XLIB Termination                                                  12
  140.   8. Using XLIB in High-Level Language Libraries                       13
  141.  
  142.  
  143.   TABLES
  144.                                                                      Page
  145.   1. XLIB Segments and Selectors by Public Symbol                       3
  146.   2. CALLPM/ENTERPM Register Storage Locations by Public Symbol         6
  147.   3. CALLRM Register Storage Locations by Public Symbol                 6
  148.  
  149.  
  150.   EXAMPLES
  151.                                                                      Page
  152.   1. Simple Mode Switching Under XLIB                                   2
  153.   2. Calling Protected-Mode Libraries From BASIC                       13
  154.  
  155.  
  156.   APPENDICES
  157.                                                                      Page
  158.   A. Summary of XLIB Public Data                                       17
  159.   B. Summary of XLIB Public Procedures                                 19
  160.   C. XLIB Error Codes                                                  27
  161.   D. Calling Protected-Mode Libraries From C                           28
  162.   E. Reporting Problems With XLIB                                      30
  163.   F. DPMI 1.0 Error Codes                                              31
  164.   G. XMS Error Codes                                                   32
  165.   H. The SWITCHPM and SWITCHRM Procedures                              33
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.                                  1. Introduction
  173.  
  174.  
  175.        XLIB is an assembly language library which may be used with assembly
  176.   language programs to greatly simplify protected-mode programming under the
  177.   Microsoft DOS operating system.  Assembly language programmers can be writing
  178.   protected-mode code in a matter of minutes with XLIB.  Implementation of such
  179.   code will often require no more than placing the code in the proper segment
  180.   and making two calls to XLIB procedures.
  181.        XLIB is designed for the Intel 386, 486, and Pentium processors.  XLIB
  182.   fully utilizes the 32-bit processing powers of these chips and makes these
  183.   powers available to the user.  The compactness of XLIB follows largely from
  184.   the fact that much of it is written in 32-bit code.
  185.        XLIB procedures handle important tasks such as mode switching between
  186.   real and protected modes, memory management under protected mode, and
  187.   interrupt management under protected mode.  XLIB includes routines to perform
  188.   these tasks in the absence of a protected mode interface, or in the presence
  189.   of the Virtual Control Program Interface (VCPI), or the DOS Protected Mode
  190.   Interface (DPMI, version .9 or higher).  XLIB can also manage extended memory
  191.   through the Extended Memory Specification (XMS).  Upon initialization, XLIB
  192.   will examine the operating environment for the presence of these interfaces
  193.   and then configure itself accordingly.  The client program may therefore
  194.   perform calls to XLIB procedures with few concerns as to the environment in
  195.   which it is executing.
  196.        XLIB relieves the programmer of descriptor table management by supplying
  197.   a set of predefined segments along with their associated descriptors and
  198.   selectors.  Many protected-mode procedures will require no modification for
  199.   XLIB other than being placed in the proper segment.  XLIB provides a single
  200.   32-bit segment for protected-mode routines.  This segment may be larger than
  201.   64K, but must reside in conventional memory so that DOS can load it.  However,
  202.   code within this segment may access data throughout the address space.
  203.        The memory model supported by XLIB approximates the flat model of IBM
  204.   OS/2 and Microsoft Windows NT.  Therefore, code written for XLIB will require
  205.   little modification when being transported to these systems.  Indeed, many
  206.   procedures will require no modification whatsoever.  Moreover, XLIB includes
  207.   flat-model descriptors which may be used to execute genuine flat-model code;
  208.   however, it does not include routines to load and relocate such code.
  209.        The following program illustrates the simplicity with which protected-
  210.   mode execution may be initiated and terminated with XLIB.  The program first
  211.   initializes XLIB by calling a procedure called INITXLIB.  After confirming
  212.   that initialization is successful, the program then transfers control to a 32-
  213.   bit protected-mode procedure which prints a message to the screen.  Control is
  214.   transferred by placing the protected-mode target address on the stack and then
  215.   calling an XLIB procedure named CALLPM (call protected mode).  CALLPM will
  216.   expect the target procedure to be contained in a segment called TSEG.  The
  217.   protected-mode procedure in TSEG returns control to real or virtual 8086 (V86)
  218.   mode simply by executing the RET instruction.
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.                                         1
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.   Example 1:  Simple Mode Switching Under XLIB
  237.   -----------------------------------------------------------------------------
  238.                  .MODEL        LARGE,PASCAL
  239.                  .386P
  240.  
  241.                  INCLUDE        XLIB.INC       ;Include XLIB public symbols
  242.                  INCLUDELIB     XLIB.LIB       ;Link with XLIB.LIB
  243.  
  244.                  .STACK         1024
  245.                  .CODE
  246.                  .STARTUP
  247.                  CALL           INITXLIB       ;Initialize XLIB
  248.                  OR             EAX,EAX        ;EAX = 0 if successful
  249.                  JZ             INITDONE
  250.                  .EXIT          0              ;Initialization failed
  251.  
  252.   INITDONE:      PUSHD          OFFSET DEMOPROC
  253.                  CALL           CALLPM         ;Execute DEMOPROC in protected
  254.                  .EXIT          0
  255.  
  256.   ;Protected-mode routines must be placed in following segment:
  257.   TSEG           SEGMENT PARA PUBLIC USE32 'CODE'
  258.                  ASSUME CS:TSEG, SS:TSEG, DS:TSEG, ES:TSEG, FS:DSEG, GS:DGROUP
  259.  
  260.   ;Protected-mode routine to print message to the screen using DOS function.
  261.   DEMOPROC       PROC NEAR
  262.                  MOV            EBX,OFFSET PMMSG
  263.                  MOV            AH,02H
  264.   MSGLOOP:       MOV            DL,CS:[EBX]    ;32-bit offset!!!!!
  265.                  OR             DL,DL
  266.                  JZ             EXIT
  267.                  INT            21H            ;Print character with DOS
  268.                  INC            EBX
  269.                  JMP            MSGLOOP
  270.   EXIT:          RET                           ;Go back to real or V86 mode
  271.   PMMSG          DB  "In 32-bit protected mode!!!  "
  272.                  DB  "Returning to real mode.",10,13,0
  273.   DEMOPROC       ENDP
  274.  
  275.   TSEG           ENDS
  276.                  END
  277.   -----------------------------------------------------------------------------
  278.  
  279.  
  280.        XLIB was developed and tested under Microsoft DOS version 6.0 using
  281.   Microsoft Assembler (MASM) version 6.1a, Microsoft LINK version 5.31.009, and
  282.   Microsoft LIB version 3.20.01.  MASM parameters were set to c, W2, and WX.
  283.   LINK parameters were set to BATCH, CPARM:1, FAR, NOPACKF, and PACKC.  XLIB has
  284.   also been tested under Microsoft Windows 3.1, Qualitas 386MAX version 6.02,
  285.   Quarterdeck QEMM version 6.02, and Quarterdeck QDPMI version 1.01.
  286.        Assembly language programs should use the CPARM:1 parameter because XLIB
  287.   will generally attempt to allocate DOS memory.  The NOPACKC option for LINK
  288.   was found to be problematic for 32-bit segments and should therefore be
  289.   avoided.
  290.  
  291.  
  292.  
  293.                                         2
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.                         2. XLIB Conventions and Structure
  301.  
  302.  
  303.        A summary of most XLIB public data is included in Appendix A.  A summary
  304.   of all XLIB public procedures is included in Appendix B.  This section sets
  305.   forth rules which will be generally applicable to XLIB data and procedures.
  306.   Exceptions to these rules are covered in Appendix H.
  307.        Though it is sometimes necessary for XLIB to distinguish between real
  308.   mode and virtual 8086 mode; this document uses the term "real mode" to include
  309.   virtual 8086 mode.
  310.        All public XLIB real-mode procedures are located in a 16-bit segment
  311.   called CSEG.  The user may also place code in CSEG but is never required to do
  312.   so.  All public XLIB real-mode routines have far returns.
  313.        All public XLIB protected-mode procedures are located in a 32-bit segment
  314.   called TSEG.  The user must also place all protected-mode code in TSEG.  All
  315.   XLIB protected-mode procedures have near returns.  Likewise, all protected-
  316.   mode procedures called by XLIB routines must have near returns.
  317.        All XLIB procedures may be called with interrupts enabled and will return
  318.   with interrupts enabled provided that they were enabled upon call.
  319.        All XLIB data is contained in a segment called DSEG.  The user may also
  320.   place data in DSEG but is never required to do so.
  321.        XLIB uses the Pascal calling and naming convention.  The Pascal
  322.   convention is equivalent to the BASIC/FORTRAN convention.  C programmers must
  323.   adapt XLIB procedures and symbols with declarations which specify the Pascal
  324.   convention.  The header file XLIB.H contains such declarations.
  325.        XLIB routines which may possibly encounter error conditions will always
  326.   return error codes in AX (see Appendix C).  In many cases, DX or the high word
  327.   of EAX will be returned with specific information about the error, such as
  328.   XMS, DPMI, or DOS error codes.
  329.        Selectors for all XLIB segments are placed in public WORD locations in
  330.   segment DSEG.  The following table gives the name of each predefined selector
  331.   along with its associated segment name and description:
  332.  
  333.  
  334.   Table 1:  XLIB Segments and Selectors by Public Symbol
  335.   -----------------------------------------------------------------------------
  336.   Selector Name    Segment Name      Description
  337.   CSEGSEL          CSEG              XLIB 16-bit code segment
  338.   CSEGDSEL         CSEG              Data selector to CSEG
  339.   TSEGSEL          TSEG              32-bit code segment
  340.   TSEGDSEL         TSEG              Data selector to TSEG
  341.   DSEGSEL          DSEG              XLIB data segment
  342.   FLATSEL          .                 Flat-model code selector
  343.   FLATDSEL         .                 Flat-model data selector
  344.   DGROUPSEL        DGROUP            DGROUP data group
  345.   SCRNSEL          .                 Screen data (color or monochrome)
  346.   -----------------------------------------------------------------------------
  347.  
  348.  
  349.        The flat-model and TSEG descriptors have limit FFFFFFFFH.  All other
  350.   descriptors have limit FFFFH.  The screen descriptor has base set to B8000H
  351.   for color monitors and B0000H for monochrome monitors.  The data descriptors
  352.   have their big bits set; consequently, implicit stack instructions will use
  353.   ESP rather then SP.  All code segments are readable and nonconforming.
  354.  
  355.  
  356.  
  357.                                         3
  358.  
  359.  
  360.  
  361.  
  362.  
  363.  
  364.   Descriptor privilege levels and requested privilege levels are set to zero
  365.   unless DPMI is installed.  Privilege levels under DPMI will be dictated by the
  366.   DPMI host, but will generally be set to three.
  367.        The values contained in the above selectors will be different under DPMI
  368.   than other environments.  Moreover, DPMI selectors values can differ under
  369.   different DPMI environments depending upon the DPMI host and the presence of
  370.   other DPMI clients.  The user should therefore always read selector values
  371.   from these locations.
  372.        Since selectors are contained in DSEG, the user must never lose track of
  373.   the DSEG selector.  This could prove a problem in interrupt handlers where no
  374.   assumptions can be made as to segment register contents.  Consequently, XLIB
  375.   places a copy of the DSEG selector in TSEG where it can always be found.  It
  376.   is stored under WORD symbol CSDSEGSEL and may be read with CS segment
  377.   override.  For example from TSEG code you can always load DS with DSEGSEL
  378.   using MOV DS,CS:CSDSEGSEL.
  379.        TSEG may be larger than 64K provided that certain rules are observed.
  380.   First, only 32-bit protected-mode code should be placed in TSEG.  The
  381.   processor will not generally be able to execute real-mode code in this segment
  382.   because the offsets will be 32-bit values.  Second, real-mode code should
  383.   never write to or read from TSEG.  Such instructions will also require 32-bit
  384.   offsets.  If you need to make modifications to TSEG, then do them from a TSEG
  385.   protected-mode procedure.  Finally, never encode segment constants in TSEG.
  386.   For example, the symbols CSEG, TSEG, DSEG, and DGROUP should never be found in
  387.   TSEG.  DOS will not be able to perform relocation fixups on these constants if
  388.   they are in a segment larger than 64K.  To read these values from TSEG,
  389.   initialize memory locations in a 16-bit segment to the values and then read
  390.   the memory locations.  Memory locations in DSEG have already been initialized
  391.   for XLIB segments.  See Appendix A.
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.                                         4
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.                                 3. Mode Switching
  429.  
  430.  
  431.        As illustrated in Example 1, CALLPM may be used to transfer control to
  432.   protected mode.  When execution is returned to real mode after CALLPM, only
  433.   segment registers and ESP are restored to their original values.  Real mode
  434.   receives other registers (except EFLAGS) at values as of the protected-mode
  435.   RET instruction.  Control may be returned from protected mode to real mode
  436.   either by RET or by a near jump to RETPM (return from protected mode).  RETPM
  437.   is an XLIB procedure which successfully returns control to real mode
  438.   regardless of stack state.
  439.        Execution may also be transferred to protected mode with the ENTERPM
  440.   (enter protected mode) procedure.  This procedure is specially designed to
  441.   accommodate mixed language programming with high-level languages operating in
  442.   real mode.  High-level language modules may be linked with libraries
  443.   containing protected-mode procedures.  These procedures may then be called
  444.   from high-level code.  However, such procedures must generally be careful to
  445.   preserve register state.  ENTERPM restores register state as required by
  446.   Microsoft high-level languages.  In particular, ENTERPM restores all 16-bit
  447.   and 32-bit registers (including system and control flags in EFLAGS) except EAX
  448.   and EDX.  EAX and EDX are not restored since these are typically used by high-
  449.   level languages for return values.  ENTERPM otherwise functions exactly as
  450.   CALLPM.
  451.        Both CALLPM and ENTERPM save register state as of call; however, upon
  452.   return to real mode, CALLPM restores only segment registers and ESP while
  453.   ENTERPM restores all registers except EAX and EDX.  CALLPM and ENTERPM will
  454.   also save and restore the state of the floating point unit (FPU) if requested.
  455.   FPU save/restore can be enabled by setting bit 2 of OFLAGS (operation flags).
  456.   The bit is clear by default.  OFLAGS is a public WORD in DSEG.
  457.        FPU state is saved with the FSAVE instruction executed from real mode.
  458.   This instruction resets the FPU; consequently, the FPU control word must be
  459.   redefined.  XLIB will therefore load FPUCW (FPU control word) to the FPU
  460.   control word after performing FSAVE.  FPUCW is a public WORD location in DSEG.
  461.   FPU state is restored with the FRSTOR instruction executed in real mode.
  462.        Control may be returned to real mode after ENTERPM either with the RET
  463.   instruction or by a near jump to EXITPM.  EXITPM will return control to real
  464.   mode regardless of stack state.
  465.        The return address placed on the stack by CALLPM is actually a near
  466.   return to RETPM.  Likewise, ENTERPM places a near return to EXITPM.  CALLPM
  467.   and ENTERPM are otherwise identical procedures.  EXITPM restores all registers
  468.   except EAX and EDX.  RETPM restores only segment registers and ESP.
  469.        CALLPM and ENTERPM save registers to public locations in DSEG.  The
  470.   following table specifies the symbols under which the registers are stored.
  471.   The calling stack is always saved after the real-mode return address and the
  472.   protected-mode target address have been popped from it.
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.                                         5
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.   Table 2:  CALLPM/ENTERPM Register Storage Locations by Public Symbol
  493.   -----------------------------------------------------------------------------
  494.   Register           Symbol              Symbol Type
  495.   EBX                ORGEBX              DWORD
  496.   ECX                ORGECX              DWORD
  497.   ESI                ORGESI              DWORD
  498.   EDI                ORGEDI              DWORD
  499.   EBP                ORGEBP              DWORD
  500.   ESP                ORGESP              DWORD
  501.   EFLAGS             ORGEFLAGS           DWORD
  502.   SS                 ORGSS               WORD
  503.   DS                 ORGDS               WORD
  504.   ES                 ORGES               WORD
  505.   FS                 ORGFS               WORD
  506.   GS                 ORGGS               WORD
  507.   FPU State          ORGFPU              BYTE[94]
  508.   -----------------------------------------------------------------------------
  509.  
  510.  
  511.        The protected-mode targets of CALLPM and ENTERPM receive the XLIB
  512.   protected mode stack (SS = TSEGSEL) with 1000H bytes of free space.  The
  513.   target also receives DS = FLATDSEL (flat-model data selector), ES = TSEGDSEL
  514.   (TSEG data selector), FS = DSEGSEL (DSEG selector), and GS = DGROUPSEL (DGROUP
  515.   selector).  The target procedure may switch stacks if desired.
  516.        Once within protected mode, far procedures in real mode can be called
  517.   using CALLRM (call real mode), which is a near procedure in TSEG.  CALLRM
  518.   should be called with the real-mode target address on the stack (push segment
  519.   first)  CALLRM saves and restores only segments registers and ESP.  The target
  520.   address receives the XLIB real-mode stack (SS = DSEG) with 200H free bytes, DS
  521.   = DGROUP, and ES = DSEG.  Code called by this routine cannot perform XLIB
  522.   shifts back to protected mode.  This excludes usage of the XLIB memory
  523.   management procedures and XLIB interrupt-vector management procedures since
  524.   these require protected-mode execution.
  525.        CALLRM saves segment registers and ESP at public locations in DSEG.  The
  526.   following table specifies the symbols under which the registers are stored.
  527.   The calling stack is saved after popping the protected-mode near return and
  528.   the real-mode target address.
  529.  
  530.  
  531.   Table 3:  CALLRM Register Storage Locations by Public Symbol
  532.   -----------------------------------------------------------------------------
  533.   Register           Symbol              Symbol Type
  534.   ESP                CALLESP             DWORD
  535.   SS                 CALLSS              WORD
  536.   DS                 CALLDS              WORD
  537.   ES                 CALLES              WORD
  538.   FS                 CALLFS              WORD
  539.   GS                 CALLGS              WORD
  540.   -----------------------------------------------------------------------------
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.                                         6
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.                              4. Interrupt Management
  557.  
  558.  
  559.        XLIB handles nearly all interrupts occurring in protected mode by
  560.   shifting to real mode and calling the inherited real-mode interrupt handlers.
  561.   All interrupts are handled this way except the keyboard interrupt (IRQ 1) and
  562.   the FPU interrupt (IRQ 13).  XLIB has its own handlers for these routines.
  563.   These handlers are activated as of protected-mode entry through CALLPM or
  564.   ENTERPM.  They remain active during calls back to real mode through CALLRM.
  565.   They are disabled upon return to CALLPM/ENTERPM.  The user may replace or
  566.   disable these handlers if desired.
  567.        It is generally desirable for the user to be able to terminate a program
  568.   or subroutine with a certain keypress combination.  Unfortunately, it is
  569.   difficult to safely abort protected-mode execution from an interrupt handler.
  570.   This is particularly the case under DPMI.  The DPMI host traps all interrupts
  571.   before transferring control to the interrupt handler.  If control is not
  572.   returned back to the host with an IRET instruction, the host will be left in
  573.   an irregular and potentially unstable state.  Similar problems could occur
  574.   under a VCPI multitasking control program.  Consequently, a keyboard interrupt
  575.   handler cannot be safely used to immediately abort execution upon a keypress.
  576.        The XLIB keyboard interrupt handler provides the best alternative.  The
  577.   handler examines keyboard input to determine if a user definable hot key has
  578.   been pressed.  If a pressed key is not the hot key, the interrupt handler
  579.   cascades the interrupt to the inherited real-mode handler.  If the hot key is
  580.   pressed, then a flag is placed in a DWORD condition code whose linear address
  581.   is stored in CCODEPTR (condition code pointer).  CCODEPRR is a public DWORD in
  582.   DSEG.  The condition code may then be polled by code in the main thread of
  583.   execution where termination can be safely accomplished.  The hot key is not
  584.   cascaded.
  585.        The hot key specification is stored in DSEG at a public WORD location
  586.   called HOTKEY.  The lower byte of HOTKEY contains the scan code of the hot key
  587.   while the upper byte specifies the state of the shift keys.  Bit 8 specifies
  588.   the state of SHIFT; bit 9 specifies CTRL, and bit 10 specifies ALT.  All other
  589.   bits are ignored.  Set bits require that the designated shift key be pressed.
  590.   The default setting for HOTKEY is 022EH (CTRL C).  The condition code flag for
  591.   the hot key is included among XLIB error codes in Appendix C.
  592.        By default CCODEPTR contains the linear address to public DWORD location
  593.   CCODE which is in DSEG.  Therefore, the hot key flag would be written to CCODE
  594.   by default.  CCODEPTR may be changed by the user; however, it must point to an
  595.   address in conventional memory.
  596.        The XLIB interrupt handler for the FPU performs three functions upon the
  597.   occurrence of any FPU exception that is unmasked in the FPU control word.
  598.   First, an error code is loaded to EAX and is also recorded at the linear
  599.   address in CCODEPTR.  Next, the FPU is initialized with FNINIT (the FPU
  600.   control word is preserved).  Third, control is transferred to EXITPM to return
  601.   to real mode.  The high word stored in EAX and the condition code will be the
  602.   FPU status word.  This word may be examined to determine the nature of the
  603.   exception.
  604.        The response of the FPU to exception conditions is largely determined by
  605.   the settings in the FPU control word.  If FPU save/restore is enabled, then
  606.   the FPU control word will be set to FPUCW upon execution of CALLPM/ENTERPM.
  607.   The default value for FPUCW is 0332H.  This sets rounding control to nearest,
  608.   precision control to 64 bits, and unmasks exceptions for overflow, zero
  609.   divide, and invalid operations.  Exceptions for underflow, precision, and
  610.  
  611.  
  612.  
  613.                                         7
  614.  
  615.  
  616.  
  617.  
  618.  
  619.  
  620.   denormalized operations are masked, and are therefore handled internally by
  621.   the FPU.  FPUCW may be modified by the user.
  622.        As explained above, the machine may be left in an unstable state after
  623.   code has been terminated from within an interrupt handler.  This is also the
  624.   case for the FPU interrupt handler.  If an FPU exception occurs under DPMI or
  625.   under a VCPI-based multitasker, then the machine may need rebooting.  Most
  626.   DPMI hosts appear to be restored to normal state by execution of INT 21
  627.   function 4CH (DOS termination).  However, this approach is not recommended in
  628.   the DPMI specifications, and should be particularly suspect under a
  629.   multitasker.  It is generally safe to continue execution after an FPU
  630.   exception when running in a single-task environment under VCPI or when running
  631.   in the absence of both DPMI and VCPI.  The user may therefore wish to debug
  632.   FPU code in these sorts of environments.
  633.        Bit 0 of OFLAGS is used by XLIB to simultaneously enable or disable all
  634.   of its own interrupt handlers.  Setting the bit enables the handlers.  XLIB
  635.   sets this bit upon calls to CALLPM/ENTERPM and clears the bit upon return.
  636.   All interrupts are cascaded to the inherited real-mode handlers when the bit
  637.   is clear.
  638.        The keyboard interrupt handler may be permanently disabled by setting
  639.   HOTKEY to zero.  This follows since no key has a zero scan code.  With HOTKEY
  640.   = 0, all keyboard interrupts are cascaded to the inherited real-mode handler.
  641.        The FPU exception handler may be permanently disabled by setting bit 1 in
  642.   OFLAGS.  If this bit is set, then the FPU interrupt handler simply cascades
  643.   the interrupt to the inherited real-mode handler.  XLIB will set the bit
  644.   during initialization if an FPU is not present; it is otherwise cleared.
  645.        Real-mode software interrupts which receive or return values in segment
  646.   registers cannot be used within protected mode because the deflection routine
  647.   will restore selectors to segment registers upon completion of the interrupt.
  648.   To use such software interrupts, one must switch to real mode through CALLRM;
  649.   issue the interrupt, and then transfer the segment registers to other
  650.   registers before returning to protected mode.
  651.        The user may install real-mode interrupt handlers in usual fashion.  Such
  652.   handlers will also receive interrupts occurring in protected mode provided
  653.   that the protected-mode handlers cascade the interrupt.  Protected-mode
  654.   interrupts will be deflected to real mode either by XLIB or by the DPMI host.
  655.   If XLIB deflects the interrupt, then the handler will receive SS = DSEG with
  656.   ESP set to 200H free bytes.  Stack sizes under DPMI will depend upon the host.
  657.        The DOS routines to get and set interrupt vectors (INT 21H functions 35H
  658.   and 25H) receive and return values through segment registers; consequently,
  659.   they cannot be used in protected mode.  Instead, use the XLIB procedures
  660.   PMGETRMIV and PMSETRMIV (protected mode - get/set real-mode interrupt vector).
  661.   Call PMGETRMIV with the interrupt number in AL.  The handler address is
  662.   returned in CX:DX.  Call PMSETRMIV with the interrupt number in AL and the new
  663.   handler address in CX:DX.
  664.        The user may install a protected-mode interrupt handler from real mode by
  665.   calling SETPMIV (set protected-mode interrupt vector).  Call with the
  666.   interrupt number in AL and the address of the new handler in CX:EDX (CX is a
  667.   selector).  This routine returns an error code in EAX (EAX returned as zero if
  668.   successful).  The current protected-mode interrupt vector may be obtained by
  669.   calling GETPMIV.  Call with AL equal to the interrupt number.  The current
  670.   handler address is returned in CX:EDX.  This routine is always successful.
  671.   These routines should not be used to manage vectors for CPU exceptions when
  672.   DPMI is active.  Direct calls to DPMI functions should be executed for these
  673.   purposes.
  674.  
  675.  
  676.  
  677.                                         8
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.        From protected mode, interrupt vectors can be managed with PMSETPMIV and
  685.   PMGETPMIV.  These procedures have the same specifications as SETPMIV and
  686.   GETPMIV.
  687.        Interrupt handlers installed with SETPMIV/PMSETPMIV are never disabled by
  688.   XLIB and will therefore always be active under protected-mode execution.
  689.   These handlers will not be active under real-mode execution in tha absence of
  690.   DPMI.  That is, real-mode interrupts are never deflected to protected mode in
  691.   such environments.  However if DPMI is active, then all hardware interrupts
  692.   (IRQs 0-15) and the software interrupts:  1CH (BIOS timer tick), 23H (DOS CTRL
  693.   C), and 24H (DOS critical error) are deflected from real mode to the installed
  694.   protected-mode handler.  If the user has not installed protected-mode handlers
  695.   for these interrupts, then they are serviced by default handlers in the DPMI
  696.   host.  The default handlers service the interrupts with the inherited real-
  697.   mode handlers.
  698.        Under DPMI, all hardware interrupts and software interrupts 0-7 will
  699.   receive control with interrupts disabled.  Since DPMI virtualizes the
  700.   interrupt flag, the IRET instruction may not reenable interrupts.
  701.   Consequently, all handlers for these interrupts should execute STI before
  702.   executing IRET.  This is not a concern if the interrupts are cascaded.
  703.        Hardware interrupts IRQ 0 through IRQ 7 are typically assigned to
  704.   interrupt numbers 08H through 0FH, while IRQs 8 through 15 are typically
  705.   assigned interrupt numbers 70H through 77H.  However, IRQs may be remapped
  706.   under either VCPI or DPMI.  The current mappings may be loaded from IRQ0INTNO
  707.   (IRQ 0 interrupt number) and IRQ8INTNO.  These are public BYTE locations in
  708.   DSEG.  They should be read only after the call to INITXLIB.
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739.  
  740.  
  741.                                         9
  742.  
  743.  
  744.  
  745.  
  746.  
  747.  
  748.                                5. Memory Management
  749.  
  750.  
  751.        XLIB supplies memory management procedures for both real mode and
  752.   protected mode.  These procedures are configured at initialization to work
  753.   with the currently resident memory management interfaces.
  754.        Conventional memory may be allocated and released in real mode through
  755.   DOS in usual fashion (INT 21H functions 48H and 49H).  However, DOS functions
  756.   may not work properly in protected mode.  Therefore, use the XLIB routines
  757.   PMGETDOSMEM and PMFREEDOSMEM for such requests.  Call PMGETDOSMEM with the
  758.   requested number of bytes in EAX.  If successful (EAX returned as zero), then
  759.   the linear address of the allocated block is returned in EDX; the allocated
  760.   block size is returned in ECX and will be at least as large as the requested
  761.   size.  A block handle is returned in EBX.  Call PMFREEDOSMEM to release a
  762.   previously allocated block.  The block handle should be in EAX upon call.
  763.        Call PMGETDOSMEM with EAX = 0 to get the largest available DOS memory
  764.   block.  The call is successful if EAX is returned as zero, in which event the
  765.   size of the largest available block will be in ECX (EBX and EDX are
  766.   preserved).
  767.        The real-mode extended memory management procedures are GETMEM, FREEMEM,
  768.   and RESETMEM.  Allocate memory by calling GETMEM with the number of bytes
  769.   requested in EAX.  With successful execution (EAX returned as zero), GETMEM
  770.   will return with the linear address of the allocated extended memory block in
  771.   EDX.  The size of the allocated block will be returned in ECX and will be at
  772.   least as large as the requested size.  The memory block handle will be
  773.   returned in EBX.  Release the block by calling FREEMEM with the block handle
  774.   in EAX.  Release all previously allocated extended memory at once by calling
  775.   RESETMEM.
  776.        The protected-mode memory management procedures are PMGETMEM, PMFREEMEM,
  777.   and PMRESETMEM.  These procedures function exactly as the corresponding real-
  778.   mode procedures:  GETMEM, FREEMEM, and RESETMEM.
  779.        GETMEM and PMGETMEM can also be used to obtain the size of the largest
  780.   available extended memory block (not total free memory).  Call with EAX = 0
  781.   for this purpose.  If this call is successful (EAX returned as zero), then the
  782.   size of the largest free block will be returned in ECX (EBX and EDX are
  783.   preserved).
  784.        XLIB will seek extended memory through XMS only if it is present and if
  785.   both DPMI and VCPI are absent.  If either protected-mode interface is present,
  786.   then all extended memory will be allocated through the configured interface.
  787.        XLIB will not use XMS to allocate memory from the high memory area (HMA)
  788.   or from upper memory blocks (UMBs).  XLIB will however allocate from the HMA
  789.   when it has full responsibility for extended memory management (DPMI, VCPI,
  790.   and XMS are all absent).  XLIB never issues calls under the Expanded Memory
  791.   Specification (EMS).
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805.                                         10
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.                               6. XLIB Initialization
  813.  
  814.  
  815.        Most XLIB procedures should be called only after XLIB has been
  816.   initialized by calling INITXLIB.  This procedure will examine the operating
  817.   environment for the presence of DPMI, VCPI, and XMS.  It will then perform
  818.   extensive code modifications upon itself to accommodate the resident software.
  819.   INITXLIB is to be called only once within a program.  Subsequent calls have no
  820.   effect.
  821.        If XLIB finds that neither DPMI nor VCPI are present, then XLIB will
  822.   completely handle all mode switching and interrupt management.  If XLIB finds
  823.   that XMS is absent also, then XLIB will handle all extended memory management.
  824.   If XLIB finds that both DPMI and VCPI are present, then it will configure
  825.   itself for DPMI by default.  However, the default may be changed by setting
  826.   bit 0 of IFLAGS (initialization flags) before calling INITXLIB.  If this bit
  827.   is set, then VCPI is given priority over DPMI.  IFLAGS is a public WORD
  828.   location in DSEG.
  829.        INITXLIB will probably attempt to allocate some conventional memory
  830.   through DOS.  Since high-level language modules and assembly language modules
  831.   often claim all available DOS memory by default, INITXLIB may fail for lack of
  832.   available DOS memory.  This problem can be averted with assembly language
  833.   modules by linking with the CPARM:1 parameter.  This forces the assembly
  834.   language module to claim no more DOS memory than is necessary.  High-level
  835.   language modules should call XLIBMEMREQ (XLIB memory requirements) to obtain
  836.   conventional memory requirements in DX:AX (measured in bytes), and then
  837.   release at least this much memory.  This process is illustrated for Microsoft
  838.   BASIC in the next example.  C does not allocate all DOS memory and therefore
  839.   does not require such special action.
  840.        If both VCPI and DPMI are present, then conventional memory requirements
  841.   will depend upon which of these interfaces is to be chosen by INITXLIB.  In
  842.   such cases, XLIBMEMREQ will return DPMI memory requirements if bit 0 of IFLAGS
  843.   is clear, and will return VCPI requirements otherwise.  Therefore, this bit
  844.   should be set to the appropriate value by the user before calling XLIBMEMREQ.
  845.   DPMI conventional memory requirements may by obtained in DX:AX by calling
  846.   DPMIMEMREQ.  VCPI conventional memory requirements may be obtained in DX:AX by
  847.   calling VCPIMEMREQ.
  848.        The XLIB routine XLIBCONFIG (XLIB configuration) returns the results of
  849.   INITXLIB.  The initialized protected-mode configuration is returned in AX.
  850.   The value of the lower nibble specifies the configured protected-mode
  851.   interface.  The value will be 1 for DPMI, 2 for VCPI, and 3 for XLIB.  Bit 4
  852.   of AX will be set if XMS is configured.  XLIBCONFIG is a real-mode routine.
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.  
  868.  
  869.                                         11
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.                                7. XLIB Termination
  877.  
  878.  
  879.        XLIB is terminated simply by executing INT 21 function 4CH (DOS
  880.   termination) from real mode.  This function must not be called from protected
  881.   mode.  Upon termination, XLIB releases all previously allocated memory and
  882.   resets all interrupt vectors to their original values.
  883.        Termination of DPMI requires that INT 21 function 4CH be executed from
  884.   protected mode.  XLIB intercepts INT 21 calls and determines if the function
  885.   number is 4CH.  If so, and if DPMI is active, then XLIB shifts to protected
  886.   mode and issues the call.
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.  
  933.                                         12
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.                   8. Using XLIB in High-Level Language Libraries
  941.  
  942.  
  943.        The following program illustrates the usage of XLIB in libraries called
  944.   from Microsoft BASIC 7.0.  The library contains a protected-mode procedure
  945.   which sums the elements in a single precision array created within BASIC.  The
  946.   general methodolgy here is recommended for developing assembly language
  947.   libraries.
  948.        Since BASIC cannot call a 32-bit segment, a real-mode interface procedure
  949.   must be placed in a 16-bit segment to receive the BASIC call and then transfer
  950.   execution to 32-bit protected mode.  The interface procedure is call SUMARRAY
  951.   while the 32-bit protected-mode procedure which actually sums the array
  952.   elements is called SUMARRAY32.
  953.        BASIC must pass certain arguments to the library procedures.  These
  954.   include the array address and the number of elements to be summed.  These
  955.   arguments could be passed on the stack; however, such approach proves awkward
  956.   since the stack must be changed when entering protected mode.  Consequently,
  957.   BASIC places all arguments in a contiguous block of memory called a "control
  958.   block," and then passes only the address of the control block to the library.
  959.   BASIC constructs the control block with a user-defined type.
  960.        The first four bytes of the control block are reserved for placement of
  961.   error codes by the library procedures.  Also, the address of the control block
  962.   is placed in CCODEPTR so that any FPU exceptions will be signalled in the
  963.   error code location as well.  Were an FPU exception to occur, the FPU
  964.   interrupt handler will immediately transfer control to EXITPM which will shift
  965.   to real-mode, restore registers, and return control to BASIC.
  966.        The library also contains a real-mode function called LINADR which may be
  967.   called by BASIC to convert segment addresses to linear addresses.
  968.        An example of this same program for Microsoft C 7.0 is included in
  969.   Appendix D.
  970.  
  971.  
  972.   Example 2:  Calling Protected-Mode Libraries From BASIC
  973.   -----------------------------------------------------------------------------
  974.                             +++++++++++++++++++++++++
  975.                             + ASSEMBLY CODE LIBRARY +
  976.                             +++++++++++++++++++++++++
  977.  
  978.  
  979.   ;The following library should be combined with XLIB.LIB using the Microsoft
  980.   ;LINK and LIB utilities.  If BASIC is to be executed from the QBX
  981.   ;environment, then a quick library must be loaded with the environment.  See
  982.   ;BASIC documentation for instructions.
  983.  
  984.  
  985.                  .MODEL         LARGE,PASCAL
  986.                  .386P
  987.  
  988.                  INCLUDE        XLIB.INC
  989.  
  990.   CSEG           SEGMENT PARA PUBLIC USE16 'CODE'
  991.                  ASSUME CS:CSEG, DS:DSEG
  992.  
  993.  
  994.  
  995.  
  996.  
  997.                                         13
  998.  
  999.  
  1000.  
  1001.  
  1002.  
  1003.  
  1004.   ;Function to calculate linear address from segment address on stack.
  1005.   ;Returns linear address in DX:AX.
  1006.   LINADR         PROC FAR PUBLIC,
  1007.                  SEGADR:DWORD                  ;Segment address of variable
  1008.                  XOR            EAX,EAX        ;Clear high words
  1009.                  XOR            EDX,EDX
  1010.                  MOV            AX,WORD PTR SEGADR[0]
  1011.                  MOV            DX,WORD PTR SEGADR[2]
  1012.                  SHL            EDX,4          ;Calculate linear address
  1013.                  ADD            EDX,EAX
  1014.                  MOV            AX,DX
  1015.                  SHR            EDX,16         ;Return linear address in DX:AX
  1016.                  RET
  1017.   LINADR         ENDP
  1018.  
  1019.   ;Structure defining control block for SUMARRAY.
  1020.   ARRAYDATA      STRUCT
  1021.     CONDCODE     DWORD          0              ;Condition code
  1022.     N            DWORD          0              ;Number of elements to sum
  1023.     ADDRESS      DWORD          0              ;Address of first element
  1024.     SUM          DWORD          0              ;Sum of array elements
  1025.   ARRAYDATA      ENDS
  1026.  
  1027.   ;Real-mode interface to SUMARRAY32.  Segment address of control block having
  1028.   ;structure ARRAYDATA should be on the stack.
  1029.   SUMARRAY       PROC FAR PUBLIC,
  1030.                  CBSEGADR:DWORD                ;Control block segment address
  1031.                  PUSH           DS
  1032.                  PUSHW          DSEG
  1033.                  POP            DS
  1034.                  XOR            EAX,EAX        ;Clear high words
  1035.                  XOR            EDX,EDX
  1036.                  MOV            AX,WORD PTR CBSEGADR[2]
  1037.                  MOV            DX,WORD PTR CBSEGADR[0]
  1038.                  SHL            EAX,4          ;Calculate linear address
  1039.                  ADD            EAX,EDX
  1040.                  MOV            CCODEPTR,EAX   ;Reset condition code address
  1041.                  POP            DS             ;Pop calling DS
  1042.                  PUSHD          OFFSET SUMARRAY32
  1043.                  CALL           ENTERPM        ;Execute SUMARRAY32 in protected
  1044.                  RET
  1045.   SUMARRAY       ENDP
  1046.  
  1047.   CSEG           ENDS
  1048.  
  1049.   TSEG           SEGMENT PARA PUBLIC USE32 'CODE'
  1050.                  ASSUME CS:TSEG, SS:TSEG, DS:TSEG, ES:TSEG, FS:DSEG, GS:DGROUP
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.                                         14
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.   ;Sum the elements of a single precision array.  Array parameters are stored
  1069.   ;in a control block having structure of ARRAYDATA.  The linear address of the
  1070.   ;control block is stored at CCODEPTR.  An error code of -1 is returned in the
  1071.   ;condition code of the control block if the number of array elements is zero
  1072.   ;XLIB places an error code in the control block if an FPU exception occurs
  1073.   ;while calculating the sum.  This error code will have the FPU status word in
  1074.   ;the high word and the XLIB FPU error code in the low word.  Observe that this
  1075.   ;routine will be called with DS = FLATDSEL (flat-model data descriptor) and
  1076.   ;FS = DSEGSEL (DSEG data descriptor).
  1077.   SUMARRAY32     PROC NEAR
  1078.                  MOV            EBX,FS:CCODEPTR               ;Get control block
  1079.                  MOV            EDX,ARRAYDATA.ADDRESS[EBX]    ;Get array address
  1080.                  MOV            ESI,ARRAYDATA.N[EBX]          ;Get N
  1081.                  SUB            ESI,1
  1082.                  JB             NODATA                        ;Error:  N = 0
  1083.                  FLDZ                                         ;Initialize sum
  1084.   SUMLOOP:       FADD           DWORD PTR [EDX+4*ESI]
  1085.                  SUB            ESI,1
  1086.                  JAE            SUMLOOP
  1087.                  FSTP           ARRAYDATA.SUM[EBX]            ;Save sum
  1088.                  RET
  1089.   NODATA:        MOV            ARRAYDATA.CONDCODE[EBX],-1    ;Record error code
  1090.                  RET
  1091.   SUMARRAY32     ENDP
  1092.  
  1093.   TSEG           ENDS
  1094.                  END
  1095.  
  1096.  
  1097.                               +++++++++++++++++++++
  1098.                               + BASIC MAIN MODULE +
  1099.                               +++++++++++++++++++++
  1100.  
  1101.  
  1102.   'The following Microsoft BASIC 7.0 program should be linked with the above
  1103.   'library.  The BASIC program first initializes XLIB.  Next, it creates a
  1104.   'single precision array.  A control block for SUMARRAY is then constructed
  1105.   'and the call to SUMARRAY is executed.  Finally, the condition code in the
  1106.   'control block is inspected and results are printed.
  1107.  
  1108.   DEFINT A-Z
  1109.  
  1110.   'Declare XLIB procedures
  1111.   DECLARE FUNCTION XLIBMEMREQ& ()
  1112.   DECLARE FUNCTION INITXLIB& ()
  1113.   DECLARE FUNCTION XLIBCONFIG% ()
  1114.  
  1115.   'Declare procedures in the library linked with XLIB
  1116.   DECLARE FUNCTION LINADR& (SEG VARIABLE AS ANY)
  1117.   DECLARE SUB SUMARRAY (SEG VARIABLE AS ANY)
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.                                         15
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132.   'Structure for the control block
  1133.   TYPE ARRAYDATA
  1134.     CONDCODE AS LONG      'Location to receive any error codes
  1135.     N AS LONG             'Number of elements to be summed
  1136.     ADDRESS AS LONG       'Linear address of the array
  1137.     SUM AS SINGLE         'Location for array sum
  1138.   END TYPE
  1139.  
  1140.   'Check XLIBCONFIG to see if XLIB has already been initialized.  If not then
  1141.   'call XLIBMEMREQ to find amount of conventional memory needed by XLIB and
  1142.   'release at least this amount with the BASIC SETMEM function.  XLIBMEMREQ
  1143.   'returns with sign bit of DX set if an error occurred.  The error is then
  1144.   'identified by AX.  XLIB will not be terminated upon completion of this
  1145.   'program in the Microsoft QBX environment; therefore, initialization is
  1146.   'required only once within the environment.
  1147.   IF XLIBCONFIG = 0 THEN
  1148.     TEMP& = XLIBMEMREQ
  1149.     IF TEMP& >= 0& THEN
  1150.       IF TEMP& > 0 THEN TEMP& = SETMEM(-TEMP& - 16&)
  1151.       TEMP& = INITXLIB                 'INITXLIB error code returned in TEMP&
  1152.     ELSE
  1153.       TEMP& = TEMP& AND &H7FFFFFFF     'Mask sign bit to leave error code only
  1154.     END IF
  1155.     IF TEMP& THEN
  1156.       PRINT "Library initialization error:  "; HEX$(TEMP&)
  1157.       END
  1158.     END IF
  1159.   END IF
  1160.  
  1161.   DIM A(100) AS SINGLE
  1162.   DIM AD AS ARRAYDATA
  1163.  
  1164.   FOR I = 0 TO 100            'Assign numbers to array
  1165.     A(I) = I
  1166.   NEXT I
  1167.  
  1168.   AD.CONDCODE = 0&            'Clear the error code
  1169.   AD.N = 50&                  'Sum first 50 elements
  1170.   AD.ADDRESS = LINADR(A(0))   'Calculate and record linear address of A(0)
  1171.  
  1172.   CALL SUMARRAY(AD)
  1173.  
  1174.   IF AD.CONDCODE THEN
  1175.     PRINT "Error: ";HEX$(AD.CONDCODE)
  1176.   ELSE
  1177.     PRINT "Sum: ";AD.SUM      'Should equal 1225
  1178.   ENDIF
  1179.  
  1180.   END
  1181.   -----------------------------------------------------------------------------
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.                                         16
  1190.  
  1191.  
  1192.  
  1193.  
  1194.  
  1195.  
  1196.                      Appendix A: Summary of XLIB Public Data
  1197.  
  1198.  
  1199.        The following is a summary of most public symbols located in the XLIB
  1200.   data segment DSEG.  This summary excludes the symbols presented in tables one
  1201.   through three.  All XLIB symbols conform to the Pascal naming convention.
  1202.  
  1203.  
  1204.   Symbols:  CSEGVAL, TSEGVAL, DSEGVAL, DGROUPVAL (Segment Values)
  1205.   Symbol Types:  WORD
  1206.   Default Settings:  CSEG, TSEG, DSEG, DGROUP
  1207.   Descriptions:  These are memory locations initialized to the respective
  1208.   segment values.  Code in TSEG should not contain segment constants since DOS
  1209.   may not be able to handle them in relocation fixups.  Read these locations to
  1210.   get segment values.  User segments should be handled the same way.
  1211.  
  1212.   Symbols:  CCODEPTR/CCODE (Condition Code Pointer/Condition Code)
  1213.   Symbol Types:  DWORD/DWORD
  1214.   Default Settings:  CCODEPTR = linear address of CCODE.  CCODE = 0.
  1215.   Descriptions:  XLIB interrupt handlers will place flags in the condition code
  1216.   to signal the occurrence of the interrupt.  CCODEPTR initially contains the
  1217.   linear address of CCODE.  CCODEPTR may be changed by the user, but must point
  1218.   to a DWORD in conventional memory.
  1219.  
  1220.   Symbol:  FPUCW (Floating Point Unit Control Word)
  1221.   Symbol Type:  WORD
  1222.   Default Setting:  0332H
  1223.   Description:  FPUCW is optionally loaded to the FPU control word by CALLPM and
  1224.   ENTERPM.  The default sets rounding control to nearest, precision control to
  1225.   64 bits, and unmasks exceptions for:  overflow, zero divide, and invalid
  1226.   operations.  Exceptions for underflow, precision, and denormalized operations
  1227.   are masked, and are therefore handled internally by the FPU.  Set bit 2 of
  1228.   OFLAGS to enable FPU save/restore and load of FPUCW.
  1229.  
  1230.   Symbol:  HOTKEY (Hot Key)
  1231.   Symbol Type:  WORD
  1232.   Default Setting:  022EH
  1233.   Description:  HOTKEY specifies the hot key for the keyboard interrupt handler.
  1234.   The low byte of HOTKEY specifies the scan code for the key.  The upper byte
  1235.   specifies the state of the shift keys.  Bit 8 specifies SHIFT; bit 9 specifies
  1236.   CTLR, and bit 10 specifies ALT.  Set bits mean that the designated key must be
  1237.   pressed.  All other bits are ignored.  The default hot key is CTRL C.  Bypass
  1238.   hot key detection by setting HOTKEY = 0.
  1239.  
  1240.   Symbol:  IFLAGS (Initialization Flags)
  1241.   Symbol Type:  WORD
  1242.   Default Setting:  0
  1243.   Description:  IFLAGS is used by INITXLIB to control the initialization
  1244.   process.  Bit 0 of IFLAGS determines DPMI/VCPI priority in the event that both
  1245.   interfaces are present.  If this bit is clear then DPMI will be installed in
  1246.   such cases.  The other bits are reserved.
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.                                         17
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.   Symbols:  IRQ0INTNO/IRQ8INTNO (IRQ X Interrupt Number)
  1261.   Symbol Types:  BYTE/BYTE
  1262.   Default Settings:  08H/70H
  1263.   Descriptions:  Specifies the interrupt number assigned to IRQ X.  IRQs 0
  1264.   through 7 and IRQs 8 through 15 are assigned to contiguous interrupt numbers.
  1265.   These locations are valid only after call to INITXLIB.
  1266.  
  1267.   Symbol:  OFLAGS (Operation Flags)
  1268.   Symbol Type:  WORD
  1269.   Default Setting:  0
  1270.   Description:  OFLAGS controls post-initialization operation of XLIB.
  1271.      Setting bit 0 disables XLIB interrupt handlers.  XLIB sets this bit only at
  1272.   calls to CALLPM and ENTERPM and then clears the bit upon return.
  1273.      Setting bit 1 causes all FPU interrupts to be cascaded to the inherited
  1274.   real-mode interrupt handler.  This bit is automatically set if no FPU is
  1275.   present.
  1276.      Setting bit 2 enables FPU save/restore in CALLPM and ENTERPM.  Setting this
  1277.   bit also causes load of FPUCW to the FPU control word.
  1278.  
  1279.  
  1280.  
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286.  
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.                                         18
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324.                   Appendix B: Summary of XLIB Public Procedures
  1325.  
  1326.  
  1327.        The following is a summary of all XLIB public procedures.  All procedures
  1328.   entered from real mode are in CSEG and have far returns.  All protected-mode
  1329.   procedures are in TSEG and have 32-bit near returns.  All procedures conform
  1330.   to the Pascal naming and calling convention.  All XLIB procedures may be
  1331.   called with interrupts enabled and will return with interrupts enabled
  1332.   provided that they were enabled upon call.
  1333.  
  1334.  
  1335.   Initialization Routines
  1336.  
  1337.  
  1338.   XLIBMEMREQ (XLIB Memory Requirements)
  1339.   Purpose:  Find XLIB conventional memory requirements.
  1340.   CPU Mode:  Real
  1341.   Registers at Call:  None
  1342.   Return Registers:
  1343.      Sign bit of DX clear if successful.  Memory requirements in bytes returned
  1344.   in DX:AX.  DX:AX is upward adjusted to an integer multiple of 16.
  1345.      Sign bit of DX set if unsuccessful.  Error code returned in AX (always DOS
  1346.   error code).
  1347.   Details:
  1348.      This routine will return DX:AX = 0 if XLIB contains free internal memory in
  1349.   sufficient quantity to meet conventional memory demands.
  1350.      If both DPMI and VCPI are present, then XLIBMEMREQ will assume that DPMI
  1351.   will be used if bit 0 of IFLAGS is clear (the default); otherwise, VCPI is
  1352.   assumed.  No additional conventional memory is needed if both DPMI and VCPI
  1353.   are absent.
  1354.  
  1355.   DPMIMEMREQ  (DPMI Memory Requirements)
  1356.   Purpose:  Find DPMI conventional memory requirements.
  1357.   CPU Mode:  Real
  1358.   Registers at Call:  None
  1359.   Return Registers:  DX:AX = conventional memory requirements adjusted upward to
  1360.   integer multiple of 16.
  1361.   Details:
  1362.      This routine will return DX:AX = 0 if XLIB contains free internal memory in
  1363.   sufficient quantity to meet the conventional memory demands of DPMI.
  1364.      This routine does not assume the presence of DPMI.  It will return DX:AX =
  1365.   0 if DPMI is absent.
  1366.  
  1367.   VCPIMEMREQ (VCPI Memory Requirements)
  1368.   Purpose:  Find VCPI conventional memory requirements.
  1369.   CPU Mode:  Real
  1370.   Registers at Call:  None
  1371.   Return Registers:  DX:AX = conventional memory requirements adjusted upward to
  1372.   integer multiple of 16.
  1373.   Details:  This routine simply loads DX:AX with a constant.
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.                                         19
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.   INITXLIB (Initialize XLIB)
  1389.   Purpose:  Check for presence of XMS, DPMI, and VCPI.  Configure XLIB
  1390.   accordingly.
  1391.   CPU Mode:  Real
  1392.   Registers at Call:  None
  1393.   Return Registers:
  1394.      AX = 0 if successful, in which event DX and EAX are zero as well.
  1395.      AX <> 0 if unsuccessful.  XLIB error code returned in AX.  Specific error
  1396.   code returned in DX and in high word of EAX (EAH).  If AX = operating
  1397.   environment identification error or DOS memory allocation error, then DX and
  1398.   EAH = DOS error code.  If AX = DPMI error, then DX and EAH = DPMI 1.0 error
  1399.   code (if provided by host).  If AX = VCPI error, then DX and EAH are returned
  1400.   as zero.
  1401.   Details:
  1402.      If both DPMI and VCPI are present, then XLIB will be configured for DPMI if
  1403.   the zero bit of IFLAGS is clear.  If this bit is set, then XLIB will be
  1404.   configured for VCPI.  The bit is clear by default.
  1405.      This routine will likely attempt to allocate DOS memory; consequently, some
  1406.   DOS memory must be free.  The amount of DOS memory XLIB will attempt to
  1407.   allocate can be obtained by calling XLIBMEMREQ, VCPIMEMREQ, or DPMIMEMREQ.
  1408.      This routine should be called only once within a program.  Subsequent calls
  1409.   are returned with no action.  XLIB is terminated by INT 21 function 4C (DOS
  1410.   termination) issued from real mode.
  1411.  
  1412.   XLIBCONFIG (XLIB Configuration)
  1413.   Purpose:  Get XLIB configuration.
  1414.   CPU Mode:  Real
  1415.   Registers at Call:  None
  1416.   Return Registers:
  1417.      AX = 0 if protected-mode structures not initialized.
  1418.      AX = XLIB configuration if protected-mode structures initialized.  Value of
  1419.   lower nibble identifies protected-mode host/server.  If 1 then DPMI.  If 2
  1420.   then VCPI.  If 3 then XLIB.  Bit 4 is set if XMS is initialized.
  1421.  
  1422.  
  1423.  
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.                                         20
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452.   Mode Switch Routines
  1453.  
  1454.  
  1455.        Mode switch routines require initialization of XLIB by INITXLIB.
  1456.  
  1457.  
  1458.   CALLPM (Call Protected Mode)
  1459.   Purpose:  Call protected-mode procedure in TSEG with near return.
  1460.   Mode:  Real
  1461.   Registers at Call:  SS:ESP = far real-mode return address (four bytes), near
  1462.   protected-mode target offset (four bytes).
  1463.   Return Registers:  Returns through RETPM.  See RETPM for details.
  1464.   Details:
  1465.      All CPU registers except EAX and EDX are saved.  The calling SS:ESP is
  1466.   saved at ORGSS:ORGESP after the return address and argument have been popped.
  1467.   XLIB interrupt handlers are enabled.  Entry point receives SS = TSEGDSEL with
  1468.   1000H free bytes on the stack.  The return address on the stack is a near
  1469.   return to RETPM.  Entry point receives segments DS = FLATDSEL, ES = TSEGDSEL,
  1470.   FS = DSEGSEL, and GS = DGROUPSEL.
  1471.      If bit 2 of OFLAGS is set, then the FPU state is also saved; the FPU is
  1472.   initialized, and FPUCW is loaded to the control word.
  1473.      If bit 1 of OFLAGS is set, then the XLIB interrupt handler for the FPU will
  1474.   not be enabled.
  1475.  
  1476.   RETPM (Return From Protected Mode)
  1477.   Purpose:  Return control to real mode with partial register restoration.
  1478.   CPU Mode:  Protected
  1479.   Registers at Call:  None
  1480.   Return Registers:  No return
  1481.   Details:
  1482.      RETPM switches to real mode and then restores all segment registers and ESP
  1483.   to values as of call to either CALLPM or ENTERPM.  XLIB interrupt handlers are
  1484.   disabled.  Control is then transferred to the real-mode return address as of
  1485.   call to CALLPM/ENTERPM.
  1486.      If bit 2 of OFLAGS is set, then RETPM also restores FPU state.
  1487.      RETPM will successfully execute regardless of stack state.
  1488.  
  1489.   ENTERPM (Enter Protected Mode)
  1490.   Purpose:  Call protected mode procedure in TSEG with near return.
  1491.   Mode:  Real
  1492.   Registers at Call:  SS:ESP = far real-mode return address (four bytes), near
  1493.   protected mode target offset (four bytes).
  1494.   Return Registers:  Returns through EXITPM.  See EXITPM for details.
  1495.   Details:  This routine executes exactly as CALLPM except that a near return to
  1496.   EXITPM is placed on the stack rather than to RETPM.
  1497.  
  1498.   EXITPM (Exit Protected Mode)
  1499.   Purpose:  Return control to real mode with general register restoration.
  1500.   CPU Mode:  Protected
  1501.   Registers at Call:  None
  1502.   Return Registers:  No return
  1503.   Details:
  1504.      EXITPM switches to real mode and then restores all registers except EAX and
  1505.   EDX to values as of call to either CALLPM or ENTERPM.  The system and control
  1506.  
  1507.  
  1508.  
  1509.                                         21
  1510.  
  1511.  
  1512.  
  1513.  
  1514.  
  1515.  
  1516.   flags in EFLAGS are also restored.  XLIB interrupt handlers are disabled.
  1517.   Control is then transferred to the real-mode return address as of call to
  1518.   CALLPM/ENTERPM.
  1519.      If bit 2 of OFLAGS is set, then EXITPM also restores FPU registers.
  1520.      EXITPM will successfully execute regardless of stack state.
  1521.      The XLIB FPU interrupt handler performs a jump to EXITPM upon occurrence of
  1522.   any unmasked FPU exception.
  1523.  
  1524.   CALLRM (Call a Real-Mode Procedure)
  1525.   Purpose:  From protected mode, call a real-mode procedure with far return.
  1526.   CPU Mode:  Protected
  1527.   Registers at Call:  SS:ESP = near protected-mode return address (four bytes),
  1528.   far real-mode target address (four bytes).
  1529.   Return Registers:  All segment registers and ESP are restored.
  1530.   Details:
  1531.      The calling SS:ESP is saved at CALLSS:CALLESP after popping the return
  1532.   address and arguments.  The called routine receives the XLIB real-mode stack
  1533.   (SS = DSEG) with 200H free bytes.  Data segment settings are DS = DGROUP and
  1534.   ES = DSEG.
  1535.      Code called by this routine cannot perform XLIB shifts back to protected
  1536.   mode, including calls to XLIB memory management procedures or procedures
  1537.   managing interrupt vectors.
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.  
  1546.  
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.  
  1572.  
  1573.                                         22
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580.   Memory Management Routines
  1581.  
  1582.  
  1583.        Memory management routines require initialization of XLIB by INITXLIB.
  1584.  
  1585.  
  1586.   PMGETDOSMEM (Protected Mode - Get DOS Memory)
  1587.   Purpose:  Allocate DOS memory block.
  1588.   CPU Mode:  Protected
  1589.   Registers at Call:  EAX = desired size of block in bytes.
  1590.   Return Registers:
  1591.      EAX = 0 if successful.  Block handle returned in EBX.  Number of allocated
  1592.   bytes returned in ECX.  Linear address of allocated block returned in EDX.
  1593.      EAX = error code if unsuccessful.  AX = XLIB error code.  High word of EAX
  1594.   (EAH) will be set to DOS error code.  If DPMI is active, then EAH will be DPMI
  1595.   error code (codes supplied by DPMI .9 and up).
  1596.   Details:
  1597.      The returned block size will always be an integer multiple of 16.
  1598.      Call with EAX = 0 to get largest available DOS memory block (not total free
  1599.   memory) in ECX (EAX, EBX, and EDX are preserved).
  1600.      If DPMI is active, then the handle is actually a selector with base address
  1601.   set to the linear address of the block.  If DPMI is not active, then the
  1602.   handle will be the segment of the block.
  1603.      In real mode, DOS memory may be allocated directly from DOS (INT 21H
  1604.   function 48H); however, this call will likely fail under DPMI protected mode.
  1605.  
  1606.   PMFREEDOSMEM (Protected Mode - Free DOS Memory)
  1607.   Purpose:  Release previously allocated DOS memory block.
  1608.   CPU Mode:  Protected
  1609.   Registers at Call:  EAX = block handle.
  1610.   Return Registers:  EAX = 0 if successful; otherwise, EAX = error code.  AX =
  1611.   XLIB error.  High word of EAX (EAH) will be DOS error code.  If DPMI is
  1612.   active, then EAH will equal DPMI error code (codes supplied by DPMI .9 and
  1613.   up).
  1614.   Details:  In real mode, DOS memory may be released directly by DOS (INT 21H
  1615.   function 49H); however, this call will likely fail under DPMI protected mode.
  1616.  
  1617.   GETMEM (Get Memory)
  1618.   Purpose:  Allocate extended memory block.
  1619.   CPU Mode:  Real
  1620.   Registers at Call:  EAX = desired size of block in bytes.
  1621.   Return Registers:
  1622.      EAX = 0 if successful.  Block handle returned in EBX.  Number of allocated
  1623.   bytes returned in ECX.  Logical address of allocated block returned in EDX.
  1624.      EAX = error code if unsuccessful.  AX = XLIB error code.  If DPMI is
  1625.   active, then high word of EAX (EAH) will be DPMI 1.0 error code (if provided
  1626.   by host).  If XMS is active, then EAH = XMS error code.
  1627.   Details:
  1628.      The returned block size will always be an integer multiple of eight.  Under
  1629.   XMS the returned block size will be a 1K multiple.  Under VCPI and most DPMI
  1630.   hosts, block sizes will be 4K multiples.
  1631.      If XMS is present in conjunction with either DPMI or VCPI, no extended
  1632.   memory will be requested through XMS.  All extended memory will be requested
  1633.   through the active protected-mode interface.
  1634.  
  1635.  
  1636.  
  1637.                                         23
  1638.  
  1639.  
  1640.  
  1641.  
  1642.  
  1643.  
  1644.      XMS is never used to allocate from the HMA or from UMBs.  XLIB will however
  1645.   allocate from the HMA in the absence of a memory management interface.
  1646.      Call with EAX = 0 to get largest available extended memory block (not total
  1647.   free memory) in ECX (EBX and EDX preserved).  This call can also return with
  1648.   error condition in EAX.
  1649.  
  1650.   FREEMEM (Free Memory)
  1651.   Purpose:  Release previously allocated extended memory block.
  1652.   CPU Mode:  Real
  1653.   Registers at Call:  EAX = block handle.
  1654.   Return Registers:  EAX = 0 if successful; otherwise, EAX = error code.  AX =
  1655.   XLIB error code.  If DPMI is active, then the high word of EAX (EAH) will be
  1656.   DPMI 1.0 error code (if provided by host).  If XMS is active, then EAH = XMS
  1657.   error code.
  1658.   Details:  FREEMEM does not release page tables allocated under VCPI.  Call
  1659.   RESETMEM for this purpose.
  1660.  
  1661.   RESETMEM (Reset Memory)
  1662.   Purpose:  Release all previously allocated extended memory.
  1663.   CPU Mode:  Real
  1664.   Registers at Call:  None
  1665.   Return Registers:  EAX = 0 if successful; otherwise, EAX = error code.  AX =
  1666.   XLIB error code.  If DPMI is active, then the high word of EAX (EAH) will be
  1667.   DPMI 1.0 error code (if provided by host).  If XMS is active, then EAH = XMS
  1668.   error code.
  1669.   Details:
  1670.      GETMEM will automatically allocate page tables as needed under VCPI.
  1671.   RESETMEM will release such tables.
  1672.      RESETMEM is always called upon execution of INT 21 function 4C (DOS
  1673.   termination)
  1674.  
  1675.   PMGETMEM  (Protected Mode - Get Memory)
  1676.   Purpose:  Allocate extended memory block while in protected mode.
  1677.   CPU Mode:  Protected
  1678.   Details:  This routine is the protected-mode version of GETMEM.  See GETMEM
  1679.   for specifications.
  1680.  
  1681.   PMFREEMEM  (Protected Mode - Free Memory)
  1682.   Purpose:  Free previously allocated extended memory block while in protected
  1683.   mode.
  1684.   CPU Mode:  Protected
  1685.   Details:  This routine is the protected-mode version of FREEMEM.  See FREEMEM
  1686.   for specifications.
  1687.  
  1688.   PMRESETMEM (Protected Mode - Reset Memory)
  1689.   Purpose:  Free all previously allocated extended memory while in protected
  1690.   mode.
  1691.   CPU Mode:  Protected
  1692.   Details:  This routine is the protected-mode version of RESETMEM.  See
  1693.   RESETMEM for specifications.
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.  
  1700.  
  1701.                                         24
  1702.  
  1703.  
  1704.  
  1705.  
  1706.  
  1707.  
  1708.   Interrupt Management Routines
  1709.  
  1710.  
  1711.        Interrupt management routines require initialization of XLIB by INITXLIB.
  1712.  
  1713.  
  1714.   PMGETRMIV (Protected Mode - Get Real-Mode Interrupt Vector)
  1715.   Purpose:  Retrieve address of real-mode interrupt handler.
  1716.   CPU Mode:  Protected
  1717.   Registers at Call:  AL = interrupt number.
  1718.   Return Registers:  Handler address returned in CX:DX.
  1719.   Details:  The DOS routine for this purpose (INT 21H function 35H) is not
  1720.   useful because it returns a value in ES.
  1721.  
  1722.   PMSETRMIV (Protected Mode - Set Real-Mode Interrupt Vector)
  1723.   Purpose:  Set address of real-mode interrupt handler.
  1724.   CPU Mode:  Protected
  1725.   Registers at Call:  AL = interrupt number, CX:DX = address of handler.
  1726.   Return Registers:  None
  1727.   Details:
  1728.      The DOS routine for this purpose (INT 21H function 25H) is not useful
  1729.   because it requires an argument in DS.
  1730.      Real-mode interrupt handlers will also be called when interrupts occur in
  1731.   protected mode provided that the protected-mode interrupt handler cascades the
  1732.   interrupt.  The default protected-mode handlers do in fact cascade all
  1733.   interrupts except the handler for IRQ1 (keyboard interrupt) and IRQ13 (FPU
  1734.   interrupt).  The keyboard interrupt handler cascades all interrupts except
  1735.   those caused by pressing the hot key.  The FPU interrupt handler cascades
  1736.   interrupts only if bit 1 of OFLAGS is set.
  1737.      XLIB never disables handlers installed by this procedure.
  1738.  
  1739.   GETPMIV (Get Protected-Mode Interrupt Vector)
  1740.   Purpose:  Retrieve address of protected-mode interrupt handler from interrupt
  1741.   descriptor table.
  1742.   CPU Mode:  Real
  1743.   Registers at Call:  AL = interrupt number.
  1744.   Return Registers:  Handler address returned in CX:EDX (CX is a selector).
  1745.   Details:  This routine does not return addresses of CPU exception handlers
  1746.   under DPMI.  Use DPMI functions directly for this purpose.
  1747.  
  1748.   SETPMIV (Set Protected-Mode Interrupt Vector)
  1749.   Purpose:  Set address of protected-mode interrupt handler in interrupt
  1750.   descriptor table.
  1751.   CPU Mode:  Real
  1752.   Registers at Call:  AL = interrupt number.  Handler address in CX:EDX (CX is a
  1753.   selector).
  1754.   Return Registers:  EAX = 0 if successful.  EAX = error code if unsuccessful.
  1755.   AX = XLIB error code.  If DPMI is installed then the high word of EAX will
  1756.   contain DPMI 1.0 error code (if provided by host).
  1757.   Details:
  1758.      Protected-mode interrupt handlers never receive interrupts occurring in
  1759.   real mode unless DPMI is active.  Under DPMI all hardware interrupts (IRQs 0-
  1760.   15) and software interrupts:  1CH, 23H, and 24H are deflected from real mode
  1761.   to the installed protected-mode handler.  The protected-mode handler receives
  1762.  
  1763.  
  1764.  
  1765.                                         25
  1766.  
  1767.  
  1768.  
  1769.  
  1770.  
  1771.  
  1772.   control of the interrupt first.  It may cascade the interrupt if so desired.
  1773.   If no protected-mode handler has been installed, then DPMI services these
  1774.   interrupts with the inherited real-mode handlers.
  1775.      XLIB never disables handlers installed by this procedure.
  1776.      Do not use this routine to install CPU exception handlers under DPMI.  Use
  1777.   DPMI functions directly for this purpose.
  1778.  
  1779.   PMGETPMIV (Protected Mode - Get Protected-Mode Interrupt Vector)
  1780.   Purpose:  Retrieve address of protected-mode interrupt handler from interrupt
  1781.   descriptor table.
  1782.   CPU Mode:  Protected
  1783.   Details:  This routine is the protected-mode version of GETPMIV.  See GETPMIV
  1784.   for specifications.
  1785.  
  1786.   PMSETPMIV (Protected Mode - Set Protected-Mode Interrupt Vector)
  1787.   Purpose:  Set address of protected-mode interrupt handler in interrupt
  1788.   descriptor table.
  1789.   CPU Mode:  Protected
  1790.   Details:  This routine is the protected-mode version of SETPMIV.  See SETPMIV
  1791.   for specifications.
  1792.  
  1793.  
  1794.  
  1795.  
  1796.  
  1797.  
  1798.  
  1799.  
  1800.  
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.  
  1810.  
  1811.  
  1812.  
  1813.  
  1814.  
  1815.  
  1816.  
  1817.  
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825.  
  1826.  
  1827.  
  1828.  
  1829.                                         26
  1830.  
  1831.  
  1832.  
  1833.  
  1834.  
  1835.  
  1836.                            Appendix C: XLIB Error Codes
  1837.  
  1838.  
  1839.        XLIB error codes are always returned in AX.  In many cases, the high word
  1840.   of EAX will be returned with specific information about the error, such as
  1841.   XMS, DPMI, or DOS error codes.
  1842.        Although error codes are not provided in the DPMI .9 specification, many
  1843.   DPMI .9 hosts do return DPMI 1.0 error codes.  DPMI 1.0 error codes may in
  1844.   fact be DOS error codes returned to the DPMI host by DOS.  If the sign bit
  1845.   (bit 15) of the error code is clear, then the error code was issued by DOS.
  1846.  
  1847.  
  1848.   Condition Code Flags
  1849.   01H     FPU exception
  1850.   02H     Hot key pressed
  1851.  
  1852.   General Errors
  1853.   10H     Interface not available
  1854.   11H     Unable to identify operating environment
  1855.   12H     DOS memory allocation failure
  1856.   13H     DOS memory release error
  1857.   14H     Unable to enable A20
  1858.   15H     Insufficient logical address space
  1859.   16H     Insufficient number of extended memory block handles
  1860.   17H     Bad extended memory block handle
  1861.  
  1862.   Errors Occurring Under DPMI (See Appendix F for codes returned by DPMI)
  1863.   20H     Protected mode initialization failure
  1864.   21H     Descriptor allocation error
  1865.   22H     Descriptor placement error
  1866.   23H     Unable to switch protected mode interrupt vector
  1867.   24H     Insufficient extended memory error
  1868.   25H     Extended memory allocation error
  1869.   26H     Extended memory release error
  1870.   27H     DPMI DOS memory allocation error
  1871.   28H     DPMI DOS memory release error
  1872.  
  1873.   Errors Occurring Under XMS (See Appendix G for codes returned by XMS)
  1874.   30H     Unable to measure available extended memory
  1875.   31H     Insufficient extended memory error
  1876.   32H     Extended memory allocation error
  1877.   33H     Unable to lock extended memory
  1878.   34H     Unable to unlock extended memory
  1879.   35H     Extended memory release error
  1880.  
  1881.   Errors Occurring Under VCPI
  1882.   40H     Error in determining protected mode entry point
  1883.   41H     Unable to determine physical address of DOS memory page
  1884.   42H     Unable to determine hardware interrupt mappings
  1885.   43H     Insufficient extended memory error
  1886.   44H     Unable to determine number of free extended memory pages
  1887.   45H     Extended memory allocation error
  1888.   46H     Extended memory release error
  1889.  
  1890.  
  1891.  
  1892.  
  1893.                                         27
  1894.  
  1895.  
  1896.  
  1897.  
  1898.  
  1899.  
  1900.                Appendix D: Calling Protected-Mode Libraries From C
  1901.  
  1902.  
  1903.        This appendix contains a C version of the BASIC program presented in
  1904.   Example 2.  Microsoft C version 7.0 is used to create a float array.  C then
  1905.   calls a protected-mode assembly language procedure in a library to sum the
  1906.   elements of the array.  The assembly language library is presented in Example
  1907.   2.  C calls a 16-bit procedure called SUMARRAY  This procedure then transfers
  1908.   control to a 32-bit protected-mode procedure called SUMARRAY32.  The latter
  1909.   procedure performs the actual calculations.  Parameters defining the array are
  1910.   placed in a contiguous block of memory defined by a C structure.  C passes the
  1911.   address of this structure to the library.  The first four bytes in the
  1912.   structure are reserved for error codes.  The linear address of the structure
  1913.   is placed in CCODEPTR so that any FPU exceptions will be recorded by the FPU
  1914.   interrupt handler in the error code location.  The SUMARRAY32 procedure will
  1915.   also record an error if the parameter defining the number of elements to be
  1916.   summed is zero.
  1917.        The C code is somewhat simpler than the corresponding BASIC code because
  1918.   DOS memory does not have to be released prior to calling INITXLIB.  This
  1919.   follows because C does not claim all DOS memory as does BASIC.
  1920.        C is more powerful than BASIC in that it can access data under external
  1921.   symbols whereas BASIC cannot.  Access to XLIB public data is made possible in
  1922.   C by including the header file called XLIB.H.  This file makes all XLIB public
  1923.   data and public real-mode procedures visible to C.  It also contains
  1924.   declarations which adapt the PASCAL conventions of XLIB.
  1925.  
  1926.  
  1927.   -----------------------------------------------------------------------------
  1928.                               +++++++++++++++++++++
  1929.                               +   C MAIN MODULE   +
  1930.                               +++++++++++++++++++++
  1931.  
  1932.  
  1933.   /* The following Microsoft C 7.0 program should be linked with the assembly
  1934.   language library in Example 2.  Combine the library with XLIB.LIB using the
  1935.   Microsoft Lib utility.  The C program first initializes XLIB.  Next, it
  1936.   creates a float array.  A control block for SUMARRAY is then constructed
  1937.   and the call to SUMARRAY is executed.  Finally, the condition code in the
  1938.   control block is inspected and results are printed. */
  1939.  
  1940.   #include <stdio.h>
  1941.   #include <xlib.h>
  1942.  
  1943.   extern long __far __pascal LINADR(void __far *ptr);
  1944.   extern void __far __pascal SUMARRAY(void __far *ptr);
  1945.  
  1946.   struct arraydata
  1947.   {
  1948.     long condcode;
  1949.     long n;
  1950.     long address;
  1951.     float sum;
  1952.   } ad;
  1953.  
  1954.  
  1955.  
  1956.  
  1957.                                         28
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.  
  1964.   float a[101];
  1965.  
  1966.   main()
  1967.   {
  1968.     int i;
  1969.     long temp;
  1970.  
  1971.     temp = INITXLIB();
  1972.     if (temp != 0)
  1973.     {
  1974.       printf("Initialization Error:  %lX\n",temp);
  1975.       return 0;
  1976.     }
  1977.  
  1978.     for(i = 0; i <= 100; i++)
  1979.       a[i] = i;
  1980.  
  1981.     ad.condcode = 0;
  1982.     ad.n = 50;
  1983.     ad.address = LINADR(a);
  1984.  
  1985.     SUMARRAY(&ad);
  1986.     if (ad.condcode != 0)
  1987.     {
  1988.       printf("Error:  %lX\n",ad.condcode);
  1989.       return 0;
  1990.     }
  1991.     printf("Sum:  %f\n",ad.sum);
  1992.   }
  1993.   -----------------------------------------------------------------------------
  1994.  
  1995.  
  1996.  
  1997.  
  1998.  
  1999.  
  2000.  
  2001.  
  2002.  
  2003.  
  2004.  
  2005.  
  2006.  
  2007.  
  2008.  
  2009.  
  2010.  
  2011.  
  2012.  
  2013.  
  2014.  
  2015.  
  2016.  
  2017.  
  2018.  
  2019.  
  2020.  
  2021.                                         29
  2022.  
  2023.  
  2024.  
  2025.  
  2026.  
  2027.  
  2028.                      Appendix E: Reporting Problems With XLIB
  2029.  
  2030.  
  2031.        All efforts to isolate and report problems with XLIB will be appreciated.
  2032.   The following steps will greatly facilitate bug-tracking:
  2033.  
  2034.   1) Ensure that your own program always checks the error codes returned by XLIB
  2035.   procedures.  These codes will likely resolve the problem.  If not, then make
  2036.   note of the code.
  2037.  
  2038.   2) Attempt to execute your program under DPMI, VCPI, and in the absence of
  2039.   both.  If the problem relates to memory management, then also attempt to
  2040.   execute your program in the presence of XMS but in the absence of DPMI and
  2041.   VCPI, then attempt to execute in the absence of all three interfaces.  It will
  2042.   generally be found that the problem occurs only under a specific interface.
  2043.   If so, then note the interface under which the problem occurs.
  2044.  
  2045.   3) If the problem occurs only under one interface, then attempt to execute
  2046.   your program under different implementations of the interface.  For example, a
  2047.   DPMI host is contained in Windows 3.1, 386MAX, and QDPMI.  Try executing your
  2048.   program under each host and make note of the results.  Problems occurring only
  2049.   under one host are generally indicative of bugs in the host rather than XLIB.
  2050.  
  2051.   4) Try different options on your compiler, assembler, and linker.  It is
  2052.   sometimes the case that code is not processed properly under some options.
  2053.  
  2054.   5) Report problems to:
  2055.  
  2056.   Dr. David Pyles
  2057.   TechniLib Company
  2058.   P.O. Box 6818
  2059.   Jackson, Ms. 39282
  2060.   (601) 372-7433
  2061.  
  2062.  
  2063.  
  2064.  
  2065.  
  2066.  
  2067.  
  2068.  
  2069.  
  2070.  
  2071.  
  2072.  
  2073.  
  2074.  
  2075.  
  2076.  
  2077.  
  2078.  
  2079.  
  2080.  
  2081.  
  2082.  
  2083.  
  2084.  
  2085.                                         30
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092.                          Appendix F: DPMI 1.0 Error Codes
  2093.  
  2094.  
  2095.        DPMI 1.0 error codes may in fact be DOS error codes returned to the DPMI
  2096.   host by DOS.  If the sign bit (bit 15) of the error code is clear, then the
  2097.   error code was issued by DOS.
  2098.  
  2099.  
  2100.   Number   Explanation
  2101.   8001H    Unsupported function
  2102.   8002H    Invalid state for requested operation
  2103.   8003H    System integrity would be endangered
  2104.   8004H    Deadlock situation detected by host
  2105.   8005H    Serialization request cancelled
  2106.   8010H    Resource unavailable
  2107.   8011H    Host unable to allocate descriptor
  2108.   8012H    Linear memory unavailable
  2109.   8013H    Physical memory unavailable
  2110.   8014H    Backing store unavailable
  2111.   8015H    Callback specifications cannot be allocated
  2112.   8016H    Cannot allocate handle
  2113.   8017H    Lock count limits exceeded
  2114.   8018H    Resource owned exclusively by another client
  2115.   8019H    Resource already shared by another client
  2116.   8021H    Invalid value
  2117.   8022H    Invalid selector
  2118.   8023H    Invalid handle
  2119.   8024H    Invalid callback
  2120.   8025H    Invalid linear address
  2121.   8026H    Request not supported by hardware
  2122.  
  2123.  
  2124.  
  2125.  
  2126.  
  2127.  
  2128.  
  2129.  
  2130.  
  2131.  
  2132.  
  2133.  
  2134.  
  2135.  
  2136.  
  2137.  
  2138.  
  2139.  
  2140.  
  2141.  
  2142.  
  2143.  
  2144.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.                                         31
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.                            Appendix G: XMS Error Codes
  2157.  
  2158.  
  2159.   Number   Explanation
  2160.   80H      Function not implemented
  2161.   81H      VDISK was detected
  2162.   82H      An A20 error occurred
  2163.   8EH      General driver error
  2164.   8FH      Unrecoverable driver error
  2165.   90H      HMA does not exist
  2166.   91H      HMA is already in use
  2167.   92H      Attempt to allocate less than HMAMIN of HMA
  2168.   93H      HMA is not allocated
  2169.   94H      A20 is still enabled
  2170.   A0H      All extended memory is allocated
  2171.   A1H      All available handles are allocated
  2172.   A2H      Invalid handle
  2173.   A3H      Source handle is invalid
  2174.   A4H      Source offset is invalid
  2175.   A5H      Destination handle is invalid
  2176.   A6H      Destination offset is invalid
  2177.   A7H      Length is invalid
  2178.   A8H      Move has an invalid overlap
  2179.   A9H      Parity error
  2180.   AAH      Block is not locked
  2181.   ABH      Block is locked
  2182.   ACH      Block lock count overflow
  2183.   ADH      Lock failed
  2184.   B0H      Only a smaller upper memory block (UMB) is available
  2185.   B1H      No UMB's are available
  2186.   B2H      UMB segment number is invalid
  2187.  
  2188.  
  2189.  
  2190.  
  2191.  
  2192.  
  2193.  
  2194.  
  2195.  
  2196.  
  2197.  
  2198.  
  2199.  
  2200.  
  2201.  
  2202.  
  2203.  
  2204.  
  2205.  
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.  
  2212.  
  2213.                                         32
  2214.  
  2215.  
  2216.  
  2217.  
  2218.  
  2219.  
  2220.                  Appendix H: The SWITCHPM and SWITCHRM Procedures
  2221.  
  2222.  
  2223.        SWITCHPM and SWITCHRM are procedures in CSEG which are used internally by
  2224.   XLIB.  They perform untransferred switches to protected mode and real mode.
  2225.   They are made public for users who need to perform mode switching without the
  2226.   overhead of CALLPM and ENTERPM.  These procedures perform mode switching in
  2227.   minimum CPU time.  However, they do not conform to all of the general
  2228.   conventions followed by other XLIB public procedures.
  2229.        SWITCHPM is a near procedure in CSEG which switches the CPU to 16-bit
  2230.   protected mode.  It returns to the caller.  It must be called with SS = DSEG;
  2231.   therefore, a stack must be set up in this segment.  SWITCHPM returns with CS =
  2232.   CSEGSEL and with SS, DS, ES, FS, and GS all being set to DSEGSEL.  Other
  2233.   registers are preserved.  Note that the caller is responsible for preserving
  2234.   real-mode segment registers.
  2235.        SWITCHRM is a near procedure in CSEG which switches the CPU to real mode.
  2236.   It returns to the caller.  It must be called with SS = DSEGSEL.  SWITCHRM
  2237.   returns with CS = CSEG and with SS, DS, ES, FS, and GS all being set to DSEG.
  2238.   Other registers are preserved.  Note that the caller is responsible for
  2239.   preserving protected-mode segment registers.
  2240.        These routines offer a great deal of potential for inline assembly in 16-
  2241.   bit C.  However, usage of 32-bit registers and 32-bit offsets in such code
  2242.   will necessitate the insertion of operand-size and address-size prefixes.
  2243.  
  2244.  
  2245.  
  2246.  
  2247.  
  2248.  
  2249.  
  2250.  
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256.  
  2257.  
  2258.  
  2259.  
  2260.  
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270.  
  2271.  
  2272.  
  2273.  
  2274.  
  2275.  
  2276.  
  2277.                                         33
  2278.