home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-03-25 | 169.2 KB | 4,153 lines |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- XLIB PROGRAMMER'S MANUAL
- VERSION 4.0
-
- (DOS Extender Library)
-
- TechniLib Company
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Copyright 1993 1994, by TechniLib (TM) Company
- All Rights Reserved
-
-
-
-
-
-
- TERMS OF USE AND DISTRIBUTION
-
-
- XLIB is a shareware product; therefore, unregistered copies of XLIB are
- made available free of charge so that potential purchasers will have the
- opportunity to examine and test the software before committing payment.
- Distribution of unregistered copies of XLIB to other potential users is also
- permitted and appreciated. However, usage and distribution of XLIB must
- conform to the following conditions. In the following statement, the term
- "commercial distribution," includes shareware distribution.
-
- 1) XLIB and accompanying software must be distributed together in copies of
- the original archive provided by TechniLib. Neither the archive nor
- individual files therein may be modified.
-
- 2) The XLIB archive may be distributed in combination with other shareware
- products; however, the XLIB archive may not be distributed with other
- commercially distributed software without written consent of TechniLib.
-
- 3) Copies of XLIB which have been used to develop software for commercial
- distribution must be registered before such software is marketed. Copies of
- XLIB which have been used to develop noncommercial software must be registered
- if such software is to be regularly used either by the developer or others.
-
- 4) Commercially distributed software must embed XLIB procedures in the
- software code. Files contained in the XLIB archive may not be placed in the
- distribution media.
-
- 5) XLIB is designed to offer a set of services to other executable code. XLIB
- may not be used to develop software for commercial distribution which will
- essentially offer any of these same services to other executable code.
- Exceptions to this condition require written consent of TechniLib.
-
- 6) Rights afforded by registering a single copy of XLIB pertain only to a
- single computer.
-
- 7) XLIB may be registered for a fee of $40.00 per copy. Accompany payment
- with the registration form included in the XLIB archive. Registrants will be
- entitled to the most recent version of the XLIB archive.
-
-
- DISCLAIMER OF WARRANTY
-
-
- XLIB AND ALL ACCOMPANYING SOFTWARE AND LITERATURE ARE DISTRIBUTED WITH
- THE EXCLUSION OF ANY AND ALL IMPLIED WARRANTIES, AND WITH THE EXCLUSION OF
- WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. TechniLib
- SHALL HAVE NO LIABILITY FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- RESULTING FROM THE USE OF XLIB OR ACCOMPANYING MATERIALS. The user assumes
- the entire risk of using this software.
-
-
- Copyright 1993 1994, by TechniLib (TM) Company
- All Rights Reserved
-
-
-
-
-
-
- TABLE OF CONTENTS
-
-
- CHAPTERS
- Page
- 1. Introduction 1
- 2. XLIB Conventions and Structure 4
- 3. XLIB Initialization and Termination 7
- 4. Mode Switching 10
- 5. Inline Mode Switching 14
- 6. Interrupt Management 18
- 7. Memory Management 25
- 8. File Management 29
- 9. Descriptor Management 34
- 10. Using XLIB in High-Level Language Libraries 35
- 11. Using XLIBE for Debugging and Exception Trapping 39
-
-
- TABLES
- Page
- 1. XLIB Segments and Selectors by Public Symbol 5
- 2. IFLAGS Settings for Memory Allocation Control 8
- 3. CALLPM/ENTERPM Register Storage Locations by Public Symbol 12
- 4. CALLRM Register Storage Locations by Public Symbol 13
- 5. XLIB File Control Block Structure 29
-
-
- EXAMPLES
- Page
- 1. Simple Mode Switching Under XLIB 3
- 2. Using INLINEPM/INLINERM in C 15
- 3. Calling Protected-Mode Libraries From BASIC 35
-
-
- APPENDICES
- Page
- A. Description of XLIB Public Data 43
- B. XLIB Error Codes 47
- C. DPMI 1.0 Error Codes 49
- D. XMS Error Codes 50
- E. Calling Protected-Mode Libraries From C 51
- F. Technical Support 53
- G. The SWITCHPM and SWITCHRM Procedures 54
- H. Debugging 55
-
-
-
-
-
-
-
-
-
-
-
-
-
- iii
-
-
-
-
-
-
- INDEX TO PROCEDURE SPECIFICATIONS
-
-
- Initialization Routines
-
- Name Purpose CPU Mode Page
- INITXLIB Initialize XLIB Real 8
- XLIBMEMREQ Get XLIB convention memory requirements Real 9
- DPMIMEMREQ Get DPMI conventional memory requirements Real 9
- VCPIMEMREQ Get VCPI conventional memory requirements Real 9
- XLIBCONFIG Get XLIB post-initialization configuration Real 9
-
- Mode Switch Routines
-
- Name Purpose CPU Mode Page
- CALLPM Call protected-mode procedure Real 11
- RETPM Return from protected mode to real mode Protected 11
- ENTERPM Call protected mode procedure Real 11
- EXITPM Return from protected mode to real mode Protected 12
- CALLRM Call real-mode procedure from protected mode Protected 12
-
- Inline Mode Switch Routines
-
- Name Purpose CPU Mode Page
- INLINEPM Return to caller in protected mode Real 16
- INLINERM Return to caller in real mode Protected 16
- CALL32 Call 32-bit procedure from 16-bit protected mode Protected 17
-
- Interrupt Management Routines
-
- Name Purpose CPU Mode Page
- PMGETRMIV Get real-mode interrupt vector Protected 22
- PMSETRMIV Set real-mode interrupt vector Protected 22
- GETPMIV Get protected-mode interrupt vector Real 23
- SETPMIV Set protected-mode interrupt vector Real 23
- PMGETPMIV Get protected-mode interrupt vector Protected 23
- PMSETPMIV Set protected mode interrupt vector Protected 24
- DEFLECTPM Deflect real-mode interrupt to protected mode Real 24
- SWITCHPM Perform nestable switch to protected mode Real 54
- SWITCHRM Perform nestable switch to real mode Real 54
-
- Memory Management Routines
-
- Name Purpose CPU Mode Page
- PMGETDOSMEM Allocate DOS memory block Protected 25
- PMFREEDOSMEM Release DOS memory block Protected 26
- GETMEM Allocate extended memory block Real 26
- FREEMEM Release extended memory block Real 27
- RESETMEM Release all extended memory blocks Real 27
- PMGETMEM Allocate extended memory block Protected 27
- PMFREEMEM Release extended memory block Protected 27
- PMRESETMEM Release all extended memory blocks Protected 27
- MAPIO Get logical address for memory-mapped IO device Real 28
- PMMAPIO Get logical address for memory-mapped IO device Protected 28
-
-
-
- iv
-
-
-
-
-
-
- INDEX TO PROCEDURE SPECIFICATIONS (CONTINUED)
-
-
- File Management Routines
-
- Name Purpose CPU Mode Page
- XCREATE Create file Real 30
- XOPEN Open existing file Real 30
- XCLOSE Close file Real 31
- XSAVE Save memory to created file Real 31
- XLOAD Load entire file to memory Real 31
- XWRITE Random write from memory to file Real 32
- XREAD Random read from file to memory Real 32
- PMXCREATE Create file Protected 33
- PMXOPEN Open existing file Protected 33
- PMXCLOSE Close file Protected 33
- PMXSAVE Save memory to created file Protected 33
- PMXLOAD Load entire file to memory Protected 33
- PMXWRITE Random write from memory to file Protected 33
- PMXREAD Random read from file to memory Protected 33
-
- Descriptor Management Routines
-
- Name Purpose CPU Mode Page
- SETDESC Place descriptor in local descriptor table Real 34
- PMSETDESC Place descriptor in local descriptor table Protected 34
-
- Debugging Routines (XLIBE only)
-
- Name Purpose CPU Mode Page
- SETWATCH Set debug data watchpoint Real 41
- FREEWATCH Release debug data watchpoint Real 41
- RESETWATCH Release all debug data watchpoints Real 42
- PMSETWATCH Set debug data watchpoint Protected 42
- PMFREEWATCH Release debug data watchpoint Protected 42
- PMRESETWATCH Release all debug data watchpoints Protected 42
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- v
-
-
-
-
-
-
- 1. Introduction
-
-
- XLIB is an assembly language library which greatly simplifies protected-
- mode programming under Microsoft DOS. Assembly language programmers will
- likely abandon real-mode programming after acquiring XLIB. With only two
- calls to XLIB procedures, assembly language programs can be utilizing the
- simplicity and power of 32-bit processing. C and C++ programs can harness the
- powers of 16-bit protected mode using inline assembly. Additionally, the XLIB
- archive contains a second library call EASYX which can be used by all high-
- level languages to gain access to extended memory.
- XLIB is designed for the Intel 386, 486, and Pentium processors. XLIB
- fully utilizes the 32-bit processing powers of these chips and makes these
- powers available to the user. The compactness of XLIB follows largely from
- the fact that much of it is written in 32-bit code.
- The archive for XLIB includes libraries and sample code in both Microsoft
- and Borland formats. XLIB has been successfully implemented with several
- Borland and Microsoft languages.
- The archive for version 4.0 provides a second library called XLIBE. This
- library contains all of the procedures in XLIB plus other procedures designed
- for debugging and exception trapping. XLIBE is capable of trapping exceptions
- in real mode also; therefore, it is potentially useful even to programmers who
- would otherwise have no interest in protected mode.
- XLIB is used to produce extended DOS applications. DOS is unfortunately
- limited by the fact that it is a real-mode operating system intended to manage
- only real-mode programs. Real-mode programs cannot use memory addresses
- requiring more than 20 bits, or use memory offsets requiring more than 16
- bits. Such programs are further limited by the fact that 32-bit instructions
- execute awkwardly in real-mode. When the processor is in real-mode, it will
- expect all 32-bit instructions to be preceded by at least one prefix. Each of
- these prefixes consumes one byte of memory and requires at least one clock to
- execute. Such limitations do not exist in 32-bit protected mode. Extended
- DOS applications overcome the limitations of DOS with their ability to execute
- in both real and protected modes. DOS services can be utilized from real mode
- while the 32-bit processing power of the CPU can be utilized from protected
- mode.
- There are presently several 32-bit operating systems available on the
- market. Such systems include IBM OS/2, Microsoft Windows NT, and UNIX. These
- systems can manage programs which operate exclusively in protected mode.
- There is little doubt that microcomputer programming is headed for a
- protected-mode future. However, it is not apparent at present which of these
- operating systems will prevail as the future leader. DOS remains the dominant
- system for the time being, and this may remain the case for longer than many
- anticipate because DOS is the common thread which links all of these systems.
- All of these systems have DOS emulation capabilities. Extended DOS programs
- will almost equal the native programs of these systems in power, and will far
- surpass them in compatibility.
- Future programs will likely operate exclusively in protected mode using
- the flat (unsegmented) memory model. The memory models supported by XLIB
- approximate the flat model; therefore, code written for XLIB will require
- little modification when being transported to flat-model operating
- environments. Indeed, many procedures will require no modification
- whatsoever. Moreover, XLIB includes flat-model descriptors which may be used
-
-
-
-
- 1
-
-
-
-
-
-
- to execute genuine flat-model code. XLIB does not load and relocate such
- code; however, it does provide the necessary tools to develop such procedures.
- XLIB procedures handle important tasks such as mode switching between
- real and protected modes, memory management under protected mode, protected-
- mode interrupt management, and protected-mode file management. XLIB includes
- routines to perform these tasks in the absence of a protected-mode interface,
- or in the presence of the Virtual Control Program Interface (VCPI), or the DOS
- Protected Mode Interface (DPMI, version .9 or higher). XLIB can also manage
- extended memory through the Extended Memory Specification (XMS). This
- versatility makes XLIB compatible with nearly all common operating
- environments for 386, 486, and Pentium processors.
- XMS is the standard interface for managing extended memory. HIMEM.SYS by
- Microsoft is the most commonly known XMS driver. VCPI is an older protected-
- mode interface designed to coordinate possibly several protected-mode
- programs. VCPI is an optional subset of EMS (Expanded Memory Specification).
- The most common VCPI driver is Microsoft's EMM386.SYS. DPMI is the protected-
- mode interface in Microsoft Windows and is considered the interface of the
- future (though VCPI remains popular). The more recent versions of Qualitas'
- 386MAX (version 6 and up) contain all of the above interfaces. Quarterdeck's
- QEMM386 contains XMS and VCPI. Quarterdeck supplies DPMI in a second driver
- called QDPMI. The latter is supplied free of charge but requires QEMM386.
- Upon initialization, XLIB will examine the operating environment for the
- presence of DPMI, VCPI, and XMS, and then configure itself accordingly. The
- client program may therefore perform calls to XLIB procedures with few
- concerns as to the environment in which it is executing.
- This manual assumes the reader to have some degree of familiarity with
- protected mode and a working knowledge of assembly language. If you are not
- familiar with protected mode, then read the tutorial in DONTREAD.ME. This
- tutorial is quite informative. Many readers will be able to bypass this
- manual altogether after working through the tutorial. Those unfamiliar with
- assembly language should consider using the EASYX library. This library is a
- real-mode interface to XLIB. It contains procedures which may be utilized
- without assembly language. The documentation for EASYX is included in the
- XLIB archive. The reader might wish to refer to this documentation now;
- however, the present document may still be needed for technical reference.
- XLIB relieves the programmer of descriptor table management by supplying
- a set of predefined segments along with their associated descriptors and
- selectors. Many protected-mode procedures will require no modification for
- XLIB other than being placed in the proper segment. XLIB provides a single
- 32-bit segment for protected-mode routines. This segment may be larger than
- 64K, but must reside in conventional memory so that DOS can load it. However,
- code within this segment may access data throughout the address space. XLIB
- does allow user-defined descriptors for special circumstances.
- The following program illustrates the simplicity with which protected-
- mode execution may be initiated and terminated with XLIB. The program was
- written with the Microsoft Assembler (MASM). It first initializes XLIB by
- calling a procedure called INITXLIB (initialize XLIB). After confirming that
- initialization is successful, the program then transfers control to a 32-bit
- protected-mode procedure which prints a message to the screen. Control is
- transferred by placing the protected-mode target address on the stack and then
- calling an XLIB procedure named CALLPM (call protected mode). CALLPM will
- expect the target procedure to be contained in a segment called TSEG. The
- protected-mode procedure in TSEG returns control to real or virtual 8086 (V86)
- mode simply by executing the RET instruction.
-
-
-
- 2
-
-
-
-
-
-
- Example 1: Simple Mode Switching Under XLIB
- _____________________________________________________________________________
- .MODEL LARGE,PASCAL
- .386P
-
- INCLUDE XLIB.INC ;Include XLIB public symbols
- INCLUDELIB XLIB.LIB ;Link with XLIB.LIB
-
- .STACK 1024
- .CODE
- .STARTUP
-
- CALL INITXLIB ;Initialize XLIB
- OR EAX,EAX ;EAX = 0 if successful
- JZ INITDONE
- .EXIT 0 ;Initialization failed
-
- INITDONE: PUSHD OFFSET DEMOPROC
- CALL CALLPM ;Execute DEMOPROC in protected
- .EXIT 0
-
- ;Protected-mode routines must be placed in following segment:
- TSEG SEGMENT PARA PUBLIC USE32 'CODE'
- ASSUME CS:TSEG, SS:TSEG, DS:TSEG, ES:TSEG, FS:DSEG, GS:DGROUP
-
- ;Protected-mode routine to print message to the screen using DOS function.
- DEMOPROC PROC NEAR
- MOV EBX,OFFSET PMMSG
- MOV AH,02H
- MSGLOOP: MOV DL,CS:[EBX] ;32-bit offset!!!!!
- OR DL,DL
- JZ EXIT
- INT 21H ;Print character with DOS
- INC EBX
- JMP MSGLOOP
- EXIT: RET ;Go back to real or V86 mode
- PMMSG DB "In 32-bit protected mode!!! "
- DB "Returning to real mode.",10,13,0
- DEMOPROC ENDP
-
- TSEG ENDS
- END
- _____________________________________________________________________________
-
-
- The framework presented in the above program is extremely simple;
- nonetheless, it will meet the demands of many protected-mode programs. Most
- protected-mode programs will require no further complications apart from a few
- calls to XLIB extended memory management procedures.
- To achieve the simplicity of the above program, XLIB must handle numerous
- complexities internally. This manual attempts to give the reader thorough
- insight into the workings of XLIB. It also discusses at length the numerous
- configuration options that are available to the programmer.
-
-
-
-
- 3
-
-
-
-
-
-
- 2. XLIB Conventions and Structure
-
-
- The XLIB archive contains files for both Microsoft and Borland languages.
- The files for Borland have the same names as those for Microsoft except a "B"
- is added to the base name. For example, XLIB.LIB is the XLIB library intended
- for Microsoft languages whereas XLIBB.LIB is intended for Borland languages.
- Sample code in this document is always for Microsoft languages; however,
- Borland versions may be found in the archive. Important information about
- using XLIB with Microsoft and Borland languages has been included in the
- README.DOC file.
- All instructions pertaining to XLIB.LIB also pertain to XLIBE.LIB;
- however, the latter library contains additional procedures for debugging and
- for trapping processor exceptions. XLIBE is intended for program development
- while XLIB is intended for release versions. The additional features in XLIBE
- are discussed in Chapter 11.
- The Microsoft version of XLIB was developed and tested under Microsoft
- DOS version 6.1 using Microsoft Assembler (MASM) version 6.11, Microsoft LINK
- version 5.31.009, and Microsoft LIB version 3.20.01. The Borland version of
- XLIB was developed and tested using Turbo Assembler (TASM) version 4.0, TLINK
- version 6.0, and TLIB version 4.0.
- XLIB has been tested under Microsoft Windows 3.1, Qualitas 386MAX
- versions 6.02 and 7.0, Quarterdeck QEMM386 versions 6.02 and 7.03, Quarterdeck
- QDPMI versions 1.01 and 1.03, Quarterdeck DESQview version 2.42, and IBM OS/2
- versions 2.0 and 2.1.
- XLIB public procedures and public data are explained in the following
- chapters. A detailed explanation of most XLIB public data is also included in
- Appendix A. This chapter sets forth rules which will be generally applicable
- to all XLIB data and procedures.
- Though it is sometimes necessary for XLIB to distinguish between real
- mode and virtual 8086 mode; this document uses the term "real mode" to include
- virtual 8086 mode.
- All public real-mode procedures and 16-bit protected-mode procedures in
- XLIB are located in a segment called CSEG. The user may also place code in
- CSEG but is rarely required to do so. All public XLIB procedures in CSEG have
- far returns (exceptions are noted in Appendix G).
- All public 32-bit protected-mode procedures in XLIB are located in a 32-
- bit segment called TSEG and have near returns. XLIB will also expect the user
- to place all 32-bit procedures in TSEG and will expect these procedures to
- have near returns. This policy is adopted to achieve approximation to the
- flat model.
- Nearly all XLIB protected-mode procedures are 32-bit routines. The only
- exceptions to this rule are the inline mode-switch procedures discussed in
- Chapter 5. This policy is implemented to approximate the flat model. There
- are very few circumstances in which 16-bit protected mode is preferable to 32-
- bit protected mode. One can generally increase program speed and reduce
- program size by writing the code for 32-bit segments.
- TSEG may be larger than 64K provided that certain rules are observed.
- XLIB adheres to all of the necessary rules. First, only 32-bit protected-mode
- code should be placed in TSEG. The processor will not generally be able to
- execute real-mode code in this segment because the offsets will be 32-bit
- values. Second, real-mode code should never write to or read from TSEG. Such
- instructions will also require 32-bit offsets. Modifications to TSEG should
- be done from a TSEG protected-mode procedure. Finally, segment constants
-
-
-
- 4
-
-
-
-
-
-
- should never be encoded in TSEG. For example, the symbols CSEG, TSEG, DSEG,
- and DGROUP should not be found in TSEG. DOS will not be able to perform
- relocation edits on these constants if they are in a segment larger than 64K.
- To read these values from TSEG, initialize memory locations in a 16-bit
- segment to the values and then read the memory locations. Memory locations in
- DSEG have already been initialized for XLIB segments (see Appendix A).
- Microsoft LINK will issue a warning for code segments exceeding 64K;
- however, this warning may be safely ignored provided that the above rules are
- observed.
- TASM programmers should use the LARGESTACK directive for code in TSEG.
- Without this directive, stack frames will be set up with BP and SP rather than
- EBP and ESP. The results could be disastrous if the high words of the 32-bit
- registers are nonzero, as could be the case if TSEG exceeds 64K.
- All XLIB procedures may be called with interrupts enabled. An enabled
- interrupt state will never be returned disabled.
- With one exception, all XLIB public data is contained in a 16-bit segment
- called DSEG. The user may also place data in DSEG but is seldom required to
- do so.
- XLIB uses the PASCAL calling and naming convention. The PASCAL
- convention is equivalent to the BASIC and FORTRAN conventions. C programmers
- must adapt XLIB procedures and symbols with declarations which specify the
- PASCAL convention. The header file XLIB.H contains such declarations.
- XLIB routines which can encounter error conditions will always return
- XLIB error codes in AX. A list of such error codes is presented in Appendix
- B. In most cases, DX or the high word of EAX will be returned with specific
- information about the error, such as DPMI, XMS, or DOS error codes. DPMI
- error codes are presented in Appendix C. XMS error codes are in Appendix D.
- Selectors for all XLIB segments are placed in public WORD locations in
- segment DSEG. The following table gives the name of each predefined selector
- along with its associated segment name and description:
-
-
- Table 1: XLIB Segments and Selectors by Public Symbol
- _____________________________________________________________________________
- Selector Name Segment Name Description
- ------------- ------------ -----------
- CSEGSEL CSEG XLIB 16-bit code segment
- CSEGDSEL CSEG Data selector to CSEG
- TSEGSEL TSEG 32-bit code segment
- TSEGDSEL TSEG Data selector to TSEG
- DSEGSEL DSEG XLIB data segment
- FLATSEL . Flat-model code
- FLATDSEL . Flat-model data
- DGROUPSEL DGROUP DGROUP data group
- SCRNSEL . Screen data
- MAINCSSEL . CS selector for main caller
- MAINSSSEL . SS selector for main caller
- MAINDSSEL . DS selector for main caller
- MAINESSEL . ES selector for main caller
- ILCSSEL . Inline CS selector
- ILSSSEL . Inline SS selector
- ILDSSEL . Inline DS selector
- _____________________________________________________________________________
-
-
-
-
- 5
-
-
-
-
-
-
- The flat-model and TSEG descriptors have limit FFFFFFFFH. All other
- descriptors have limit FFFFH. The screen descriptor has base set to B8000H
- for color monitors and B0000H for monochrome monitors. MAINCSSEL, MAINSSEL,
- MAINDSSEL, and MAINESSEL are selectors to descriptors which have base
- addresses matching the contents of CS, SS, DS, and ES as of the call to
- INITXLIB. ILCSSEL, ILSSSEL, and ILDSSEL are selectors used by the inline
- mode-switch procedures (see Chapter 5). The base addresses of the
- corresponding descriptors are adjusted dynamically.
- All data segments are expand-up and writable. Data descriptors also have
- their big bits set; consequently, implicit stack instructions will use ESP
- rather then SP. All code segments are readable and nonconforming. Descriptor
- privilege levels and requested privilege levels are set to zero unless DPMI is
- installed. Privilege levels under DPMI will generally be set to three.
- The values contained in the above selectors will be different under DPMI
- than other environments. Moreover, DPMI selector values can differ in
- different environments and under different hosts. Therefore, the user should
- not assume these values to be constant.
- Since selector values are stored in DSEG, the user must never lose track
- of the DSEG selector. This could prove a problem in interrupt handlers where
- no assumptions can be made as to register contents. Consequently, XLIB places
- a copy of the DSEG selector in TSEG where it can always be found. It is
- stored under WORD symbol CSDSEGSEL and may be read with CS override. For
- example from TSEG code one can always load DS with DSEGSEL using MOV
- DS,CS:CSDSEGSEL.
- XLIB never uses selectors past DGROUPSEL in Table 1. The user may
- therefore redefine the associated descriptors if desired (see Chapter 9).
- Selector values however should not be changed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 6
-
-
-
-
-
-
- 3. XLIB Initialization and Termination
-
-
- XLIB procedures apart from those presented in this chapter should be
- called only after XLIB has been initialized by calling INITXLIB. This routine
- will examine the operating environment for the presence of DPMI, VCPI, and
- XMS. It will then perform extensive code modifications upon XLIB to
- accommodate the resident software. INITXLIB is to be called only once within
- a program. Subsequent calls have no effect.
- If XLIB finds that neither DPMI nor VCPI are present, then XLIB will
- completely handle all mode switching and interrupt management. If XLIB finds
- that XMS is absent also, then XLIB will handle all extended memory management.
- If XLIB finds that both DPMI and VCPI are present, then it will configure
- itself for DPMI by default. However, the default may be changed by setting
- bit 0 of IFLAGS (initialization flags) before calling INITXLIB. If this bit
- is set, then VCPI is given priority over DPMI. IFLAGS is a public WORD
- location in DSEG.
- INITXLIB will possibly attempt to allocate some memory through DOS.
- Since high-level language modules and assembly language modules often claim
- all available conventional memory, INITXLIB may fail for lack of available
- memory. This problem can be averted with MASM programs by linking with the
- CPARM:1 parameter. This forces the program to claim no more conventional
- memory than is necessary. TASM programs and some high-level language programs
- should release memory to DOS during initialization. This process is
- illustrated for TASM in the file EXAMP1B.ASM. In some cases, the main program
- will need to retain all memory except what is necessary for XLIB. The XLIB
- procedure XLIBMEMREQ (XLIB memory requirements) may be called to obtain
- conventional memory requirements for XLIB. Usage of XLIBMEMREQ is illustrated
- for Microsoft BASIC in Chapter 10. C and C++ do not allocate all conventional
- memory and therefore do not require any special action.
- If both VCPI and DPMI are present, then conventional memory requirements
- will depend upon which of these interfaces is to be chosen by INITXLIB. In
- such cases, XLIBMEMREQ will return DPMI memory requirements if bit 0 of IFLAGS
- is clear (the default), and will return VCPI requirements otherwise.
- Therefore, this bit should be set to the appropriate value by the user before
- calling XLIBMEMREQ. DPMI conventional memory requirements may be obtained by
- calling DPMIMEMREQ. These will vary from host to host. VCPI conventional
- memory requirements may be obtained by calling VCPIMEMREQ. VCPI requires
- approximately 12K.
- One of the principle functions of XLIB is of course to make protected-
- mode interfaces and memory management interfaces transparent to the client
- program. However, there are special cases where a program should be informed
- as to which interfaces are implemented. In such cases, the procedure
- XLIBCONFIG (XLIB configuration) may be called to determine the how XLIB has
- been configured by INITXLIB.
- XLIB is terminated with INT 21H function 4CH (DOS termination) issued
- either from real or protected mode.
-
-
-
-
-
-
-
-
-
-
- 7
-
-
-
-
-
-
- Detailed Specifications
-
-
- INITXLIB (Initialize XLIB)
- Purpose: Check for presence of XMS, DPMI, and VCPI, then configure XLIB to
- operate with the installed interfaces.
- CPU Mode: Real
- Registers at Call: None
- Return Registers:
- AX = 0 if successful, in which event DX and EAX are zero as well. The
- configured interfaces may be identified by calling XLIBCONFIG (see below).
- AX <> 0 if unsuccessful. An XLIB error code is returned in AX. A specific
- error code is returned in DX and in the high word of EAX (EAH). If AX = 10H
- or 11H, then a DOS error code is returned. If AX = DPMI error, then a DPMI
- 1.0 error code is returned (if provided by host). If AX = VCPI error, then DX
- = EAH = 0. If AX = XMS error, then an XMS error code is returned.
- Details:
- If both DPMI and VCPI are present and if EMS is enabled, then XLIB will be
- configured for DPMI if the zero bit of IFLAGS is clear. If this bit is set,
- then XLIB will be configured for VCPI. The bit is clear by default. If EMS
- is disabled, then XLIB will always be configured for DPMI if it is present.
- This routine will possibly attempt to allocate conventional memory. The
- amount of memory XLIB will attempt to allocate can be obtained by calling
- XLIBMEMREQ (see below). The general address range from which this memory is
- allocated can be controlled by appropriately setting the high byte of IFLAGS.
- Alternative values for this byte are presented in Table 2. The byte has a
- value of 2 by default. This setting forces XLIB to allocate from the highest
- available address in conventional memory. Under certain settings of IFLAGS,
- XLIB can also allocate from upper memory (DOS 5.0 or higher).
- Descriptors are created for the segments loaded in CS, SS, DS, and ES as of
- call to this routine. The selectors for these descriptors are MAINCSSEL,
- MAINSSSEL, MAINDSSEL, and MAINESSEL. These descriptors are never used by
- other XLIB procedures. They are provided to augment development of protected-
- mode libraries. Protected-mode library routines may access the stack and data
- of the main program through these descriptors.
- INITXLIB should be called only once within a program. Subsequent calls are
- returned with no action. XLIB is terminated by INT 21H function 4CH (DOS
- termination) issued from either real or protected mode.
-
-
- Table 2: IFLAGS Settings for Memory Allocation Control
- _____________________________________________________________________________
- Bits 8-15 Implied Memory Allocation Location
- --------- ----------------------------------
- 00H Lowest available address in conventional memory (00000H-9FFFFH)
- 01H Best fit in conventional memory
- 02H Highest available address in conventional memory
- 40H Lowest available address in upper memory (A0000H-FFFFFH)
- 41H Best fit in upper memory
- 42H Highest available address in upper memory
- 81H Follow strategy 40H by 00H if necessary
- 82H Follow strategy 41H by 01H if necessary
- 83H Follow strategy 42H by 02H if necessary
- _____________________________________________________________________________
-
-
-
- 8
-
-
-
-
-
-
- XLIBMEMREQ (XLIB Memory Requirements)
- Purpose: Find XLIB conventional memory requirements.
- CPU Mode: Real
- Registers at Call: None
- Return Registers:
- Sign bit of DX clear if successful. Memory requirements in bytes are
- returned in DX:AX.
- Sign bit of DX set if unsuccessful. An error code is returned in AX
- (always a DOS error code).
- Details:
- DX:AX is adjusted upward to an integer multiple of 16.
- If both DPMI and VCPI are present and if EMS is enabled, then XLIBMEMREQ
- will assume that DPMI will be used if bit 0 of IFLAGS is clear (the default);
- otherwise, VCPI is assumed. If EMS is disabled, then DPMI will always be
- assumed if present. No additional conventional memory is needed if both DPMI
- and VCPI are absent.
- This routine will return DX:AX = 0 if XLIB contains free internal memory in
- sufficient quantity to meet conventional memory demands.
- This routine obtains DPMI requirements by calling DPMIMEMREQ (see below)
- and VCPI requirements by calling VCPIMEMREQ.
-
- DPMIMEMREQ (DPMI Memory Requirements)
- Purpose: Find DPMI conventional memory requirements.
- CPU Mode: Real
- Registers at Call: None
- Return Registers: DX:AX = conventional memory requirements.
- Details:
- DX:AX is adjusted upward to an integer multiple of 16.
- This routine does not assume the presence of DPMI. It will return DX:AX
- set to zero if DPMI is absent.
- This routine will return DX:AX = 0 if XLIB contains free internal memory in
- sufficient quantity to meet the conventional memory demands of DPMI.
-
- VCPIMEMREQ (VCPI Memory Requirements)
- Purpose: Find VCPI conventional memory requirements.
- CPU Mode: Real
- Registers at Call: None
- Return Registers: DX:AX = conventional memory requirements.
- Details:
- DX:AX is adjusted upward to an integer multiple of 16.
- This routine simply loads DX:AX with a constant approximately equal to
- 12Kb.
-
- XLIBCONFIG (XLIB Configuration)
- Purpose: Get XLIB configuration.
- CPU Mode: Real
- Registers at Call: None
- Return Registers: AX = 0 if protected-mode structures are not initialized;
- otherwise, AX = XLIB configuration. The value of lower nibble identifies the
- protected-mode host/server. If 1 then DPMI is installed. If 2 then VCPI is
- installed. If 3 then XLIB handles mode switches. Bit 4 is set if XMS is
- installed.
-
-
-
-
-
- 9
-
-
-
-
-
-
- 4. Mode Switching
-
-
- As illustrated in Example 1, CALLPM may be used to transfer control to
- 32-bit protected mode in segment TSEG. When execution is returned to real
- mode, segment registers, ESP, system flags, and control flags are restored to
- their original values.
- Execution may also be transferred to protected mode in TSEG with the
- ENTERPM (enter protected mode) procedure. This procedure is specially
- designed to accommodate mixed-language programming with high-level languages
- operating in real mode. High-level language modules may be linked with
- libraries containing protected-mode procedures. These procedures may then be
- called from high-level code. However, such procedures must generally be
- careful to restore register state. ENTERPM restores register state as
- required by Microsoft high-level languages. In particular, ENTERPM restores
- all registers except EAX, EDX, and the status flags. EAX and EDX are not
- restored because these are typically used by high-level languages for return
- values. ENTERPM otherwise functions exactly as CALLPM.
- Both CALLPM and ENTERPM save register state as of call. CALLPM and
- ENTERPM will also save and restore the state of the floating point unit (FPU)
- if requested. FPU save/restore can be enabled by setting bit 2 of OFLAGS
- (operation flags). The bit is clear by default. OFLAGS is a public WORD in
- DSEG.
- FPU state is saved with the FSAVE instruction executed from real mode.
- This instruction resets the FPU; consequently, the FPU control word must be
- redefined. XLIB will therefore load FPUCW (FPU control word) to the FPU
- control word after performing FSAVE. FPUCW is a public WORD location in DSEG.
- After entering protected mode through CALLPM or ENTERPM, control would
- typically be returned to real mode with the RET instruction. However, control
- may also be returned to real mode by jumping to either RETPM or EXITPM. These
- are both procedures in TSEG. They will successfully return control to real
- mode regardless of the stack state; therefore, they can be useful for
- debugging. For example, an unidentified area of protected-mode code that is
- causing the system to crash can be isolated by placing jumps to EXITPM at
- alternative locations.
- RETPM returns control to the real-mode caller of CALLPM/ENTERPM after
- restoring segment registers, ESP, system flags, and control flags. EXITPM
- returns control to the real mode caller after restoring all registers except
- EAX, EDX, and the status flags.
- The return address placed on the stack by CALLPM is actually a near
- return to RETPM. Likewise, ENTERPM places a near return to EXITPM. CALLPM
- and ENTERPM are otherwise identical procedures.
- Once within protected mode, far procedures in real mode can be called
- using CALLRM. CALLRM may be called only by protected-mode procedures in TSEG.
- XLIB contains two hardware interrupt handlers that are typically
- activated upon entry to protected mode. These handlers are fully explained in
- Chapter 6. The first handler is hooked to the keyboard interrupt. This
- handler manages hot key detection. The second handler is hooked to the FPU
- interrupt and is designed to handle FPU exceptions.
-
-
-
-
-
-
-
-
- 10
-
-
-
-
-
-
- Detailed Specifications
-
-
- CALLPM (Call Protected Mode)
- Purpose: Call a protected-mode procedure in TSEG with near return.
- CPU Mode: Real
- Registers at Call: SS:ESP = 32-bit protected-mode target offset.
- Return Registers: Returns through RETPM. See RETPM for details.
- Details:
- All CPU registers except EAX and EDX are saved at locations presented in
- Table 3. The stack is saved after the return address and argument have been
- popped.
- The target receives SS = TSEGDSEL with 1000H free bytes on the stack. The
- return address on the stack is a near return to RETPM. The target receives by
- default: DS = FLATDSEL, ES = TSEGDSEL, FS = DSEGSEL, and GS = DGROUPSEL.
- Other registers, including the status flags and interrupt flag, are received
- at values as of call.
- If bit 2 of OFLAGS is set, then the FPU state is also saved; the FPU is
- initialized, and FPUCW is loaded to the control word.
- XLIB hardware interrupt handlers are enabled (see Chapter 6). However, if
- bit 1 of OFLAGS is set, then the XLIB interrupt handler for the FPU will not
- be enabled.
- If an FPU exception occurs after CALLPM, and if the FPU exception handler
- is enabled, then protected mode will be exited through EXITPM rather than
- RETPM. If FPU save/restore is not enabled, then real-mode will receive an
- initialized FPU with control word set to the value existing as of the
- exception.
- The user may change the stack after the mode switch.
- DS, ES, FS, and GS are actually loaded from: PMDS, PMES, PMFS, and PMGS.
- These are public WORD locations in DSEG and are initialized to the default
- selectors by INITXLIB. The user however may change these selectors to any
- legal values after initialization.
-
- RETPM (Return From Protected Mode)
- Purpose: Return control to real mode with partial register restoration.
- CPU Mode: Protected
- Registers at Call: None
- Return Registers: No return
- Details:
- RETPM switches to real mode and then restores all segment registers, ESP,
- system flags, and control flags to values as of call to either CALLPM or
- ENTERPM. XLIB hardware interrupt handlers are disabled (see Chapter 6).
- Control is then transferred to the real-mode return address as of call to
- CALLPM/ENTERPM.
- If bit 2 of OFLAGS is set, then RETPM also restores FPU state.
- RETPM will successfully execute regardless of stack state.
-
- ENTERPM (Enter Protected Mode)
- Purpose: Call a protected mode procedure in TSEG with near return.
- CPU Mode: Real
- Registers at Call: SS:ESP = 32-bit protected-mode target offset.
- Return Registers: Returns through EXITPM. See EXITPM for details.
- Details: This routine executes exactly as CALLPM except that a near return to
- EXITPM is placed on the stack rather than to RETPM.
-
-
-
- 11
-
-
-
-
-
-
- EXITPM (Exit Protected Mode)
- Purpose: Return control to real mode with general register restoration.
- CPU Mode: Protected
- Registers at Call: None
- Return Registers: No return
- Details:
- EXITPM switches to real mode and then restores all registers except EAX,
- EDX, and status flags to values as of call to either CALLPM or ENTERPM. XLIB
- hardware interrupt handlers are disabled (see Chapter 6). Control is then
- transferred to the real-mode return address as of call to CALLPM/ENTERPM.
- If bit 2 of OFLAGS is set, then EXITPM also restores FPU state.
- EXITPM will successfully execute regardless of stack state.
- The FPU exception handler performs a jump to EXITPM upon occurrence of any
- unmasked FPU exception.
-
-
- Table 3: CALLPM/ENTERPM Register Storage Locations by Public Symbol
- _____________________________________________________________________________
- Register Symbol Symbol Type
- -------- ------ -----------
- EBX ORGEBX DWORD
- ECX ORGECX DWORD
- ESI ORGESI DWORD
- EDI ORGEDI DWORD
- EBP ORGEBP DWORD
- ESP ORGESP DWORD
- EFLAGS ORGEFLAGS DWORD
- SS ORGSS WORD
- DS ORGDS WORD
- ES ORGES WORD
- FS ORGFS WORD
- GS ORGGS WORD
- FPU State ORGFPU BYTE[94]
- _____________________________________________________________________________
-
-
- CALLRM (Call a Real-Mode Procedure)
- Purpose: Call a real-mode routine with far return from protected mode.
- CPU Mode: Protected
- Registers at Call: SS:ESP = far real-mode target address (four bytes).
- Return Registers: All segment registers and ESP are restored. Other
- registers, including status flags and the interrupt flag, are received with
- values as of the real-mode RET instruction.
- Details:
- This is a near procedure in TSEG. It must therefore be called from TSEG.
- Segment registers and ESP are saved at locations presented in Table 4. The
- stack is saved after popping the return address and argument.
- The target receives the XLIB real-mode stack (SS = DSEG) with 200H free
- bytes. By default, the target receives DS = DGROUP, ES = DSEG, FS = DSEG, and
- GS = DSEG. Other registers, including status flags and the interrupt flag,
- are received at values as of call.
- Code called by this routine should not perform calls to XLIB procedures
- other than SWITCHPM and SWITCHRM (see Appendix G). Most real-mode procedures
-
-
-
-
- 12
-
-
-
-
-
-
- in XLIB issue calls to CALLPM; however, neither CALLPM nor ENTERPM are
- reentrant. For example, you cannot nest CALLPM/RETPM pairs.
- DS and ES are actually loaded from RMDS and RMES. These are public WORD
- locations in DSEG and are initialized to the default values. However, the
- user may change these values if desired.
- This procedure does not change values in OFLAGS; consequently, XLIB
- hardware interrupt handlers remain enabled in real mode if they were enabled
- as of call (see Chapter 6).
- FPU exceptions in real mode are handled the same as in protected mode;
- however, system software is less apt to be left in regular state after real-
- mode exceptions. FPU instructions should therefore be executed in protected
- mode where possible.
-
-
- Table 4: CALLRM Register Storage Locations by Public Symbol
- _____________________________________________________________________________
- Register Symbol Symbol Type
- -------- ------ -----------
- ESP CALLESP DWORD
- SS CALLSS WORD
- DS CALLDS WORD
- ES CALLES WORD
- FS CALLFS WORD
- GS CALLGS WORD
- _____________________________________________________________________________
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 13
-
-
-
-
-
-
- 5. Inline Mode Switching
-
-
- XLIB includes two routines to perform mode switching in C and C++
- programs using inline assembly. These procedures are very versatile and
- simple. They switch the processor between real mode and 16-bit protected
- mode. A third routine is included to facilitate calls from 16-bit protected-
- mode to 32-bit near procedures in TSEG.
- Call INLINEPM to switch to 16-bit protected mode. Descriptors are
- automatically created for CS, SS, and DS. These registers are returned
- containing selectors to the respective descriptors. ES is returned containing
- DSEGSEL. ES may therefore be used to load other XLIB selectors to segment
- registers.
- Call INLINERM to return to real-mode. This function should be called
- from the same segment as the previous call to INLINEPM and should be using the
- same stack segment. INLINERM restores segment registers to values which
- existed as of the call to INLINEPM.
- The following Microsoft C 7.0 program illustrates the usage of these
- procedures. The program contains a C subroutine called "getextmem" which uses
- INLINEPM and INLINERM to retrieve a DWORD from extended memory.
- Since the Microsoft C 7.0 compiler does not recognize 32-bit assembly
- instructions, the following program attains access to 32-bit registers by
- encoding prefixes in front of 16-bit instructions. These prefixes are
- inserted with the _emit directive. Also observe that INLINERM is called
- indirect through a supplied pointer in DSEG called INLINERMPTR. This is done
- to ensure that the intersegment call loads CS with the protected-mode selector
- for CSEG (CSEGSEL) rather than with the segment constant.
- A Borland C version of this program is contained in the file EXAMP2B.C.
- The Borland version is somewhat simpler than the following program because 32-
- bit registers can be used in Borland C provided that TASM is used to perform
- the assembly.
- This program may fail if an attempt is made to access logical addresses
- which are either protected or undefined in the page tables.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 14
-
-
-
-
-
-
- Example 2: Using INLINEPM/INLINERM in C
- _____________________________________________________________________________
- #include <stdio.h>
- #include <xlib.h>
- #define som _emit 0x66 /*Switch operand mode*/
- #define sam _emit 0x67 /*Switch address mode*/
- long __far getextmem(long address);
- int goterr = 0; /*Error flag*/
-
- void main(void)
- {
- long l, xaddress;
- l = INITXLIB(); /*Initialize XLIB*/
- if(l != 0) /*See if an error occurred*/
- {
- printf("Library initialization error: %lX\n",l);
- return;
- }
-
- xaddress = 0x100000; /*Read first dword in 2ond meg*/
- l = getextmem(xaddress); /*See if an error occurred*/
- if(goterr != 0)
- {
- printf("Inline mode-switch error: %lX\n",l);
- return;
- }
- printf("[%lX] = %lX\n",xaddress,l);
- }
-
- long __far getextmem(long address)
- {
- __asm
- {
- som ;mov eax,[bp+6]
- mov ax,[bp+6] ; ""
- call INLINEPM ;Switch to 16-bit protected mode
- jc error ;Error code in ax
- mov ds,es:FLATDSEL ;Switch to flat data model
- sam ;push dword ptr [eax]
- som ; ""
- _emit 0ffh ; ""
- _emit 030h ; ""
- pop ax ;Return address contents in dx:ax
- pop dx
- call es:INLINERMPTR ;Switch back to real mode by calling
- jmp done ;INLINERM indirect. A direct call would
- ;load cs with an invalid value.
- error:
- xor dx,dx ;Return error code in dx:ax
- inc goterr ;Set error flag
- done:
- }
- }
- _____________________________________________________________________________
-
-
-
- 15
-
-
-
-
-
-
- Detailed Specifications
-
-
- INLINEPM (Inline Protected-Mode)
- Purpose: Return to real-mode caller in 16-bit protected mode.
- CPU Mode: Real
- Registers at Call: None
- Return Registers:
- CF clear if successful. Descriptors are created for CS, SS, and DS. These
- descriptors have base addresses matching the calling contents of the
- respective segment registers. The segment registers are returned containing
- selectors to these descriptors. These selectors are also stored in DSEG at
- the public WORD locations ILCSSEL, ILSSSEL, and ILDSSEL. See Chapter 2 for
- further details as to descriptor specifications. ES, FS, and GS are returned
- containing DSEGSEL. Protected mode receives other registers, except the
- status flags, at values as of call. System flags (including the interrupt
- flag) and control flags are preserved through the call.
- CF set if unsuccessful. The processor will still be in real mode.
- Unsuccessful execution can occur only under DPMI. EAX is returned with an
- error code. AX = XLIB error code. The high word of EAX will equal a DPMI 1.0
- error code (if provided by host). Other registers, except the status flags,
- are unchanged.
- Details:
- INLINEPM stores segment registers at the same locations used by CALLPM and
- ENTERPM (Table 1). INLINERM (see below) then restores these registers. C
- will require that other registers be preserved also; however, the user is
- responsible for managing these.
- XLIB hardware interrupt handlers are not activated by this procedure (see
- Chapter 6). The keyboard handler may be enabled by the user if hot key
- detection is needful; however, the FPU exception handler should never be
- enabled. Therefore, hot key detection should be enabled by setting both bits
- 0 and 1 in OFLAGS.
- SP is preserved through the mode switch; however, the high word of ESP is
- set to zero. The high word must be cleared since SS is set to a descriptor
- having FFFFH limit and having its big bit set.
- If multiple calls are made to INLINEPM with no changes to CS, SS, and DS,
- then descriptors are created only on the first call. Subsequent calls will
- therefore execute more quickly.
-
- INLINERM (Inline Real-Mode)
- Purpose: Return to 16-bit protected-mode caller in real mode.
- CPU Mode: 16-bit protected mode
- Registers at Call: CS and SS must equal values as of return from INLINEPM.
- Return Registers: Segment registers are restored to values existing as of
- former call to INLINEPM. Real mode receives other registers, except status
- flags, at values as of call. System flags (including the interrupt flag) and
- control flags are preserved through the call.
- Details:
- Since INLINERM will be called intersegment, caution must be taken that CS
- is loaded with CSEGSEL and not CSEG. XLIB provides a far pointer to this
- procedure called INLINERMPTR which may be used to execute the call.
- INLINERM and CALL32 are the only 16-bit protected-mode procedures in XLIB.
- They are also the only protected-mode procedures having far returns.
-
-
-
-
- 16
-
-
-
-
-
-
- CALL32 (Call 32-bit Protected-Mode)
- Purpose: Call a 32-bit protected-mode near procedure in segment TSEG from 16-
- bit protected-mode.
- CPU Mode: 16-bit protected mode
- Registers at Call: SS:ESP = 32-bit protected-mode target offset.
- Return Registers: All registers, including status flags, are returned with
- values existing as of the 32-bit RET instruction.
- Details:
- CALL32 is a far procedure; therefore, caution must be taken that calls to
- CALL32 load CS with CSEGSEL instead of CSEG. XLIB provides a far pointer to
- this procedure in DSEG called CALL32PTR which may be used to execute the call.
- CALL32 and INLINERM are the only 16-bit protected-mode procedures in XLIB.
- They are also the only protected-mode procedures having far returns.
- This procedure does not alter the state of OFLAGS.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 17
-
-
-
-
-
-
- 6. Interrupt Management
-
-
- Interrupt management is the most complicated task performed by XLIB.
- Accordingly, this chapter is the most difficult section of the user's manual.
- In general, this chapter may be ignored for programs which do not install
- interrupt handlers, do not require hot key detection, and do not use floating
- point operations.
-
-
- XLIB Interrupt Handlers
-
-
- XLIB handles nearly all interrupts occurring in protected mode by
- shifting to real mode and calling the currently installed real-mode interrupt
- handlers. In all but three cases, XLIB uses inherited real-mode handlers.
- XLIB installs its own handlers only for the DOS interrupt (INT 21H), the
- keyboard interrupt (INT 9), and the FPU interrupt (INT 75H).
- The DOS interrupt handler (INT 21H) intercepts all DOS calls and
- determines if termination is requested (AH = 4CH). If not, then the interrupt
- is immediately cascaded to DOS. If so, then XLIB performs housecleaning
- before relaying the request to DOS. Under DPMI, XLIB will restore all
- interrupt vectors and release all allocated descriptors. The DPMI host
- automatically releases all allocated memory. Under other configurations, XLIB
- will reset all real-mode interrupt vectors and release all allocated extended
- memory.
- INT 21H function 4CH may be executed in either real mode or protected
- mode. DPMI hosts will expect this function to be executed from protected
- mode; consequently, XLIB will switch to protected mode before relaying the
- request to DPMI. XLIB also installs a protected-mode handler for INT 21H
- under DPMI. This is to ensure that XLIB will see the termination request
- before the DPMI host.
- The keyboard interrupt handler is intended to facilitate termination of
- protected-mode procedures with a keypress. When a user-defined hot key is
- pressed, the keyboard interrupt handler will modify a flag variable. This
- flag variable may then be polled periodically in the main thread of execution.
- The keyboard interrupt handler is a real-mode routine.
- The inconvenience of having to poll the flag variable is unfortunately
- necessary. It is not generally safe to terminate within a hardware interrupt
- handler, particularly in protected-mode environments. A hardware interrupt
- generated by a keypress may have interrupted system software in the middle of
- a system maintenance operation. Termination in such cases would likely leave
- the system in an irregular and potentially unstable state.
- Matters are further complicated in most protected-mode environments. For
- example, a DPMI host will trap all hardware interrupts before cascading them
- to interrupt handlers. If control is not returned to the host with the IRET
- instruction, then the host will be left in an irregular state. Moreover, the
- trapping procedure will likely switch stacks before relaying the interrupt to
- the handler; consequently, the handler cannot determine the final return
- address and therefore cannot change this address to a termination procedure.
- These complications will nearly always occur when hardware interrupts are
- virtualized. Virtual 8086 mode interrupts will almost certainly be
- virtualized in either VCPI-based or DPMI-based environments.
-
-
-
-
- 18
-
-
-
-
-
-
- When a key is pressed, the keyboard interrupt handler will examine the
- key to determine if it is the hot key. If not, then the interrupt is cascaded
- to the inherited real-mode handler. If so, then a hot key flag is recorded to
- a DWORD whose linear address is recorded at CCODEPTR (condition code pointer).
- The hot key is not cascaded. CCODEPTR is a public DWORD in DSEG. The hot key
- flag is listed among XLIB error codes in Appendix B.
- CCODEPTR initially contains the linear address to public DWORD location
- CCODE which is in DSEG. Therefore, the hot key flag would be written to CCODE
- by default. CCODEPTR may be changed by the user; however, it must point to an
- address in conventional memory.
- The hot key specification is stored in DSEG at a public WORD location
- called HOTKEY. The lower byte of HOTKEY contains the scan code of the hot key
- while the upper byte specifies the state of the shift keys. Bit 8 specifies
- the state of SHIFT; bit 9 specifies CTRL, and bit 10 specifies ALT. All other
- bits are ignored. Set bits require that the designated shift key be pressed.
- The default setting for HOTKEY is zero. This setting disables hot key
- detection since no key has a zero scan code.
- The XLIB interrupt handler for FPU exceptions performs three major
- functions upon the occurrence of any FPU exception that is unmasked in the FPU
- control word. First, an error code is loaded to EAX and is also recorded at
- the linear address in CCODEPTR. Next, the FPU is initialized with FNINIT (the
- FPU control word is preserved). Third, control is transferred to EXITPM to
- return to real mode. The high word stored in EAX and in the condition code
- will be the FPU status word. This word may be examined to determine the
- nature of the exception. The FPU interrupt handler is a real-mode routine.
- The response of the FPU to exception conditions is largely determined by
- the settings in the FPU control word. If FPU save/restore is enabled, then
- the FPU control word will be set to FPUCW upon execution of CALLPM/ENTERPM.
- The default value for FPUCW is 0332H. This sets rounding control to nearest,
- precision control to 64 bits, and unmasks exceptions for overflow, zero
- divide, and invalid operations. Exceptions for underflow, precision, and
- denormalized operations are masked, and are therefore handled internally by
- the FPU. FPUCW may be modified by the user.
- As explained above, the machine may be left in an unstable state after a
- program has been terminated from within a hardware interrupt handler. This
- can also be the case for the FPU interrupt handler. However, it will be safe
- to continue execution after FPU exceptions under clean configurations. This
- follows because interrupts are not virtualized and because the exception will
- never be generated in the operating system (DOS seldom uses the FPU). Nor
- should there be any problem with continuing execution after an exception in
- protected-mode under VCPI. This follows since protected-mode interrupts
- cannot be virtualized under VCPI. Exceptions occurring in virtual 8086 mode
- or under DPMI protected mode may however leave the machine in an irregular
- state. Reboot may be necessary in these cases.
- All tested DPMI hosts appear to be restored to normal state by execution
- of INT 21H function 4CH (DOS termination). However, the DPMI specifications
- offer no guarantees to this approach. FPU exceptions in virtual 8086 mode are
- generally no problem in single-task environments; however, they will
- frequently prove problematic under a multitasker such as DESQview.
- Bit 0 of OFLAGS is used by XLIB to simultaneously enable or disable all
- of its own hardware interrupt handlers. Setting the bit enables the handlers.
- XLIB sets this bit upon calls to CALLPM/ENTERPM and clears the bit upon
- return. All interrupts are immediately cascaded to the inherited real-mode
- handlers when the bit is clear. Therefore, FPU exceptions are handled by XLIB
-
-
-
- 19
-
-
-
-
-
-
- only after calls to CALLPM/ENTERPM. Accordingly, hot key detection is enabled
- only after calls to CALLPM/ENTERPM. The user may set the bit under other
- circumstances; however, XLIB will not be able to properly handle FPU
- exceptions in these cases. The bit should be set by the user only when hot
- key detection is desired and when it is certain that the FPU exception handler
- will not be invoked.
- The FPU exception handler may be permanently disabled by setting bit 1 in
- OFLAGS. If this bit is set, then the FPU interrupt handler simply cascades
- the interrupt to the inherited real-mode handler. XLIB will set the bit
- during initialization if an FPU is not present; it is otherwise cleared.
- Real-mode software interrupts which receive or return values in segment
- registers cannot be used within protected mode because the deflection routine
- will restore selectors to segment registers upon completion of the interrupt.
- To use such software interrupts, one must switch to real mode through CALLRM;
- issue the interrupt, and then transfer the segment registers to other
- registers or to memory before returning to protected mode.
- Certain software interrupts use status flags for return flags, typically
- to signal error conditions. This is particularly the case for DOS interrupts.
- The deflection routine will pass these alterations to the code which issued
- the interrupt.
-
-
- Installation of Interrupt Handlers
-
-
- The user may install real-mode interrupt handlers in usual fashion. Such
- handlers will also receive interrupts occurring in protected mode because
- either XLIB or the DPMI host will deflect all protected-mode interrupts. If
- XLIB deflects the interrupt, then the handler will receive SS = DSEG with ESP
- set to 200H free bytes. Stack sizes under DPMI will depend upon the host, but
- must contain a minimum of 200H free bytes to meet DPMI specifications.
- The DOS routines to get and set interrupt vectors (INT 21H functions 35H
- and 25H) receive and return values through segment registers; consequently,
- they cannot be used in protected mode. Instead, use the XLIB procedures
- PMGETRMIV and PMSETRMIV (protected mode - get/set real-mode interrupt vector).
- The user may install a protected-mode interrupt handler from real mode by
- calling SETPMIV (set protected-mode interrupt vector). The current protected-
- mode interrupt vector may be obtained by calling GETPMIV.
- From protected mode, interrupt vectors can be managed with PMSETPMIV and
- PMGETPMIV. These procedures have the same specifications as SETPMIV and
- GETPMIV.
- Interrupt handlers installed with SETPMIV/PMSETPMIV are never disabled by
- XLIB and will therefore always be active under protected-mode execution.
- These handlers will not be active under real-mode execution in the absence of
- DPMI. That is, real-mode interrupts are never deflected to protected-mode
- handlers in such environments. However if DPMI is active, then all hardware
- interrupts (IRQs 0-15) and the software interrupts: 1CH (BIOS timer tick),
- 23H (DOS CTRL C), and 24H (DOS critical error) are deflected from real mode to
- the installed protected-mode handler. Therefore the protected-mode handler
- always receives the interrupt first. If the handler cascades the interrupt,
- then the real-mode handler will receive it next. If the user has not
- installed protected-mode handlers for these interrupts, then they are serviced
- by default handlers in the DPMI host. The default handlers typically deflect
- the interrupts to the real-mode handlers.
-
-
-
- 20
-
-
-
-
-
-
- If the programmer wishes to install a protected-mode interrupt handler
- for a hardware interrupt or for INT 1CH, INT 23H, or INT 24H, then
- consideration must be given to the fact that treatment of these interrupts
- will differ under different protected-mode configurations. As noted above,
- the DPMI host will always send these interrupts to the protected-mode handler
- regardless of the CPU mode in which the interrupt occurred. If DPMI is not
- installed, then protected-mode handlers receive control only under protected-
- mode interrupts. Therefore, if the protected-mode handler is to receive real-
- mode interrupts under such configurations, the programmer must install a real-
- mode handler to perform the deflection.
- XLIB includes a procedure called DEFLECTPM which can be used within a
- real-mode interrupt handler to deflect control to a protected-mode handler.
- DEFLECTPM functions only under VCPI and XLIB mode switching. If DPMI is
- installed, then the procedure returns with no action. The intent of this
- procedure is to enable simulation of DPMI treatment of hardware interrupts,
- INT 1CH, INT 23H, and INT 24H.
- Observe that if the real-mode handler deflects to the protected-mode
- handler, then the latter should not cascade the interrupt since an infinite
- loop would result. This follows because the initial protected-mode handler
- deflects to the real-mode handler.
- Were one to use DEFLECTPM in a real-mode handler for the interrupts named
- above, then the protected-mode handler will receive all interrupts regardless
- of the protected-mode configuration. This occurs naturally under DPMI.
- DEFLECTPM ensures that it will occur under other configurations. Observe that
- under DPMI, the real-mode handler will never be executed.
- A real-mode interrupt handler may need to perform shifts to protected
- mode in order to gain access to extended memory. This mode switch should not
- be performed with CALLPM or ENTERPM if there is any possibility that the
- interrupt originated in protected mode or during a call through CALLRM. This
- follows because CALLPM and ENTERPM are not reentrant; consequently, calls to
- these procedures cannot be nested. The same may be said of INLINEPM and
- INLINERM. Use the SWITCHPM and SWITCHRM procedures discussed in Appendix G
- for this purpose.
- Real-mode hardware interrupt handlers which perform shifts to protected
- mode should be installed after the call to INITXLIB. Otherwise, the first
- interrupt may occur before protected-mode structures and code have been
- initialized.
- Interrupt handler should never call XLIB procedures apart from DEFLECTPM,
- SWITCHPM, and SWITCHRM. This limitation applies to handlers in either CPU
- mode.
- It is sometimes important that interrupt handlers execute in shortest
- possible CPU time. This would typically be the case for handlers of the
- communication ports. Since mode switching is time consuming, such handlers
- should be installed for the CPU mode which is expected to receive the most
- interrupts.
- If DPMI is installed, then it is possible for multiple clients to operate
- in a single virtual machine. In such cases, DPMI will always send hardware
- interrupts to the primary client (the most recently installed client in the
- virtual machine).
- Under DPMI, all protected-mode handlers for hardware interrupts and
- software interrupts 0-7 will receive control with interrupts disabled. Since
- DPMI virtualizes the interrupt flag, the IRET instruction may not reenable
- interrupts. Consequently, all handlers for these interrupts should execute
-
-
-
-
- 21
-
-
-
-
-
-
- STI before executing IRET. Other protected-mode interrupts do not affect the
- interrupt flag.
- All real-mode interrupt handlers will receive control with interrupts
- disabled regardless of the protected-mode configuration. All protected-mode
- handlers will receive control with interrupts disabled under VCPI or XLIB mode
- switching. However, if DPMI is installed, then protected-mode software
- interrupts apart from 0-7 will receive the virtual interrupt flag at its value
- as of the INT instruction. That is, DPMI does not alter the interrupt flag in
- these cases.
- Hardware interrupts IRQ 0 through IRQ 7 are typically assigned to
- interrupt numbers 08H through 0FH, while IRQs 8 through 15 are typically
- assigned interrupt numbers 70H through 77H. However, IRQs are remapped in
- some operating environments, typically to facilitate exception handling.
- XLIBE will in fact remap hardware interrupts in some situations (see Chapter
- 11). The current mappings may be loaded from IRQ0INTNO (IRQ 0 interrupt
- number) and IRQ8INTNO. These are public BYTE locations in DSEG. They should
- be read only after the call to INITXLIB.
- DESQview does remap hardware interrupts; however, its interrupt handlers
- for the new locations generally transfer control to the addresses at the
- conventional vectors. DESQview must be started with a command-line switch if
- it is to accommodate certain hardware interrupts. In particular, the FPU
- interrupt will not function properly under DESQview unless DESQview is started
- with DV /HW:75:C.
-
-
- Detailed Specifications
-
-
- PMGETRMIV (Protected Mode - Get Real-Mode Interrupt Vector)
- Purpose: Retrieve address of real-mode interrupt handler.
- CPU Mode: Protected
- Registers at Call: AL = interrupt number.
- Return Registers: Handler address returned in CX:DX.
- Details: The DOS routine for this purpose (INT 21H function 35H) is not
- useful because it returns a value in ES.
-
- PMSETRMIV (Protected Mode - Set Real-Mode Interrupt Vector)
- Purpose: Set address of real-mode interrupt handler.
- CPU Mode: Protected
- Registers at Call: AL = interrupt number, CX:DX = address of handler.
- Return Registers: None
- Details:
- The DOS routine for this purpose (INT 21H function 25H) is not useful
- because it requires an argument in DS.
- Real-mode interrupt handlers will also be called when interrupts occur in
- protected mode provided that the protected-mode interrupt handler cascades the
- interrupt. The default protected-mode handlers do in fact cascade all
- interrupts.
- XLIB never disables handlers installed by this procedure.
-
-
-
-
-
-
-
-
- 22
-
-
-
-
-
-
- GETPMIV (Get Protected-Mode Interrupt Vector)
- Purpose: Retrieve address of protected-mode interrupt handler from interrupt
- descriptor table.
- CPU Mode: Real
- Registers at Call: AL = interrupt number.
- Return Registers: Handler address returned in CX:EDX (CX is a selector).
- Details: This routine does not return addresses of CPU exception handlers
- under DPMI. Use DPMI functions directly for this purpose.
-
- SETPMIV (Set Protected-Mode Interrupt Vector)
- Purpose: Set address of protected-mode interrupt handler in interrupt
- descriptor table.
- CPU Mode: Real
- Registers at Call: AL = interrupt number. Handler address in CX:EDX (CX is a
- selector).
- Return Registers: EAX = 0 if successful. EAX = error code if unsuccessful.
- AX = XLIB error code. If DPMI is installed then the high word of EAX will
- contain a DPMI 1.0 error code (if provided by host).
- Details:
- XLIB never disables handlers installed by this procedure.
- Protected-mode interrupt handlers never receive interrupts occurring in
- real mode unless DPMI is active. Under DPMI all hardware interrupts (IRQs 0-
- 15) and software interrupts 1CH, 23H, and 24H are deflected from real mode to
- the installed protected-mode handler. The protected-mode handler therefore
- receives control of the interrupt first. It may cascade the interrupt if so
- desired, in which event, the real-mode handler receives the interrupt next. If
- no protected-mode handler has been installed, then DPMI generally deflects the
- interrupt to the real-mode handler.
- All protected-mode handlers will receive control with interrupts disabled
- unless DPMI is installed. Under DPMI, protected-mode software interrupts
- apart from 0-7 do not alter the state of the virtual interrupt flag.
- Protected-mode handlers under DPMI for hardware interrupts and software
- interrupts 0-7 should execute STI before IRET to ensure that the virtual
- interrupt flag is enabled.
- If multiple DPMI clients are running in the same virtual machine, then the
- primary client (most recently installed client) always receives hardware
- interrupts.
- If DPMI .9 is installed, then protected-mode interrupt vectors should be
- reset to original values before termination. Such action is not required for
- DPMI 1.0.
- This routine should not be used to install CPU exception handlers under
- DPMI. DPMI functions should be used for this purpose.
-
- PMGETPMIV (Protected Mode - Get Protected-Mode Interrupt Vector)
- Purpose: Retrieve address of protected-mode interrupt handler from interrupt
- descriptor table.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of GETPMIV. See GETPMIV
- for specifications.
-
-
-
-
-
-
-
-
- 23
-
-
-
-
-
-
- PMSETPMIV (Protected Mode - Set Protected-Mode Interrupt Vector)
- Purpose: Set address of protected-mode interrupt handler in interrupt
- descriptor table.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of SETPMIV. See SETPMIV
- for specifications.
-
- DEFLECTPM (Deflect to Protected-Mode)
- Purpose: Call a protected-mode interrupt handler.
- CPU Mode: Real
- Registers at Call: SS:ESP = interrupt number (2 bytes)
- Return Registers: Segment registers are preserved through the call. The
- interrupt flag is also preserved through the call. All other registers are
- returned at values existing as of the protected-mode IRET instruction.
- Details:
- The protected-mode handler will always receive interrupts disabled. It may
- enable interrupts if desired; however, once control is returned to DEFLECTPM,
- the interrupt flag will be reset to its original value.
- This procedure can be used only under VCPI and XLIB mode switching. It
- returns with no action under DPMI. The routine is intended to simulate DPMI
- treatment of hardware interrupts, INT 1CH, INT 23H, and INT24H. The routine
- may be called from a real-mode interrupt handler to deflect the interrupt to
- the protected-mode handler.
- The protected-mode handler should not cascade the interrupt; otherwise, an
- infinite loop will result.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 24
-
-
-
-
-
-
- 7. Memory Management
-
-
- XLIB supplies memory management procedures for both real and protected
- modes. These procedures are configured at initialization to work with the
- currently resident memory management interfaces.
- Conventional memory may be allocated and released in real mode through
- DOS in usual fashion (INT 21H functions 48H and 49H). However, DOS functions
- may not work properly in protected mode. Therefore, use the XLIB routines
- PMGETDOSMEM and PMFREEDOSMEM for such requests. PMFREEDOSMEM can also be used
- to find the amount of available DOS memory.
- The real-mode extended memory management procedures are GETMEM, FREEMEM,
- and RESETMEM. GETMEM is used to allocate a block of extended memory. FREEMEM
- may then be used to release the block. RESETMEM releases all previously
- allocated blocks at once. GETMEM may also be used to find the amount of
- available extended memory.
- The protected-mode memory management procedures are PMGETMEM, PMFREEMEM,
- and PMRESETMEM. These procedures function exactly as the corresponding real-
- mode procedures: GETMEM, FREEMEM, and RESETMEM.
- XLIB will seek extended memory through XMS only if it is present and if
- both DPMI and VCPI are absent. If either protected-mode interface is present,
- then all extended memory will be allocated through the configured interface.
- XLIB will not use XMS to allocate memory from the high memory area (HMA)
- or from upper memory blocks (UMBs). XLIB will however allocate from the HMA
- when it has full responsibility for extended memory management (DPMI, VCPI,
- and XMS are all absent). XLIB never issues calls under EMS (apart from calls
- to VCPI).
- Under DPMI and VCPI, the CPU will typically be operating in page mode.
- Under this mode of operation, memory may be remapped such that logical
- addresses are not equal to physical addresses. Addresses specified in the
- instruction code are logical addresses. The physical addresses are the
- locations in memory which are actually accessed. Typically, a programmer need
- not be concerned with the difference between these two types of addresses.
- However, the difference must be recognized when working with input/output
- devices which map to certain physical location in memory. XLIB includes
- routines called MAPIO and PMMAPIO which assign logical addresses to specified
- physical addresses. The physical addresses can then be accessed via the
- assigned logical addresses.
-
-
- Detailed Specifications
-
-
- PMGETDOSMEM (Protected Mode - Get DOS Memory)
- Purpose: Allocate DOS memory block.
- CPU Mode: Protected
- Registers at Call: EAX = desired size of block in bytes.
- Return Registers:
- EAX = 0 if successful. A block handle is returned in EBX. The number of
- allocated bytes is returned in ECX. The linear address of allocated block is
- returned in EDX.
- EAX = error code if unsuccessful. AX = XLIB error code. The high word of
- EAX (EAH) will be set to a DOS error code. If DPMI is active, then EAH will
- be a DPMI error code (codes are supplied by DPMI .9 and up).
-
-
-
- 25
-
-
-
-
-
-
- Details:
- The block will always be paragraph aligned and will have size equal to an
- integer multiple of 16.
- The location in free memory from which the block is allocated will depend
- upon the allocation strategy in force as of call (see INT 21H function 58H).
- Call with EAX = 0 to get largest available DOS memory block (not total free
- memory) in ECX (EAX, EBX, and EDX are preserved).
- If DPMI is active, then the handle is actually a selector with base address
- set to the linear address of the block. If DPMI is not active, then the
- handle will be the segment of the block.
- In real mode, DOS memory may be allocated directly from DOS (INT 21H
- function 48H); however, this call will likely fail under DPMI protected mode.
-
- PMFREEDOSMEM (Protected Mode - Free DOS Memory)
- Purpose: Release previously allocated DOS memory block.
- CPU Mode: Protected
- Registers at Call: EAX = block handle.
- Return Registers: EAX = 0 if successful; otherwise, EAX = error code. AX =
- XLIB error. The high word of EAX (EAH) will be a DOS error code. If DPMI is
- active, then EAH will equal a DPMI error code (codes are supplied by DPMI .9
- and up).
- Details: In real mode, DOS memory may be released directly by DOS (INT 21H
- function 49H); however, this call will likely fail under DPMI protected mode.
-
- GETMEM (Get Memory)
- Purpose: Allocate extended memory block.
- CPU Mode: Real
- Registers at Call: EAX = desired size of block in bytes.
- Return Registers:
- EAX = 0 if successful. A block handle is returned in EBX. The number of
- allocated bytes is returned in ECX. The logical address of allocated block is
- returned in EDX.
- EAX = error code if unsuccessful. AX = XLIB error code. If DPMI is
- active, then the high word of EAX (EAH) will be a DPMI 1.0 error code (if
- provided by host). If XMS is active, then EAH = XMS error code.
- Details:
- The page size for extended memory allocations is contained in PAGESIZE.
- PAGESIZE is a DWORD in DSEG and should be read after initialization. The
- blocks will have addresses that are PAGESIZE aligned and will have sizes equal
- to an integer multiple of PAGESIZE. PAGESIZE will equal: 1024 for XMS, 4096
- for VCPI, 4096 for most DPMI hosts, and 16 in the absence of a memory manager.
- If XMS is present in conjunction with either DPMI or VCPI, no extended
- memory will be requested through XMS. All extended memory will be requested
- through the active protected-mode interface.
- XMS is never used to allocate from the HMA or from UMBs. XLIB will however
- allocate from the HMA in the absence of a memory management interface.
- Call with EAX = 0 to get largest available extended memory block (not total
- free memory) in ECX (EBX and EDX are preserved). This call can also return
- with an error condition in EAX.
-
-
-
-
-
-
-
-
- 26
-
-
-
-
-
-
- FREEMEM (Free Memory)
- Purpose: Release previously allocated extended memory block.
- CPU Mode: Real
- Registers at Call: EAX = block handle.
- Return Registers: EAX = 0 if successful; otherwise, EAX = error code. AX =
- XLIB error code. If DPMI is active, then the high word of EAX (EAH) will be a
- DPMI 1.0 error code (if provided by host). If XMS is active, then EAH = XMS
- error code.
- Details: FREEMEM does not release page tables allocated under VCPI. Call
- RESETMEM for this purpose.
-
- RESETMEM (Reset Memory)
- Purpose: Release all previously allocated extended memory.
- CPU Mode: Real
- Registers at Call: None
- Return Registers: EAX = 0 if successful; otherwise, EAX = error code. AX =
- XLIB error code. If DPMI is active, then the high word of EAX (EAH) will be a
- DPMI 1.0 error code (if provided by host). If XMS is active, then EAH = XMS
- error code.
- Details:
- GETMEM will automatically allocate page tables as needed under VCPI.
- RESETMEM will release such tables.
- If DPMI is not installed, then RESETMEM will be called upon execution of
- INT 21H function 4C (DOS termination). DPMI hosts reset extended memory
- automatically.
-
- PMGETMEM (Protected Mode - Get Memory)
- Purpose: Allocate extended memory block.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of GETMEM. See GETMEM
- for specifications.
-
- PMFREEMEM (Protected Mode - Free Memory)
- Purpose: Free previously allocated extended memory block.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of FREEMEM. See FREEMEM
- for specifications.
-
- PMRESETMEM (Protected Mode - Reset Memory)
- Purpose: Free all previously allocated extended memory.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of RESETMEM. See
- RESETMEM for specifications.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 27
-
-
-
-
-
-
- MAPIO (Map Input/Output Device)
- Purpose: Create a logical address mapping for an input/output device which
- maps to a fixed physical memory address.
- CPU Mode: Real
- Registers at Call: EDX = first physical address to be mapped. EAX = size of
- physical address block.
- Return Registers:
- EAX = 0 if successful, in which event, EDX = the logical address for
- accessing the physical memory.
- EAX = error code if unsuccessful. AX = XLIB error code. If DPMI is
- active, then the high word of EAX (EAH) will be a DPMI 1.0 error code (if
- provided by host). If XMS is active, then EAH = XMS error code.
- Details:
- DPMI will not allow mapping of physical addresses within the first
- megabyte; however, such mappings are allowed under other configurations.
- Logical addresses will always equal physical addresses in the absence of
- VCPI and DPMI because the processor will not be operating in page mode. In
- such cases, MAPIO simply performs validity checks on EDX and EAX.
- MAPIO will automatically allocate page tables as needed under VCPI.
- RESETMEM will release such tables.
- Memory-mapped input/output devices are not typically mapped within the
- range of available memory since this would leave the possibility of confusing
- such addresses with ordinary memory. Instead, such devices are mapped beyond
- the highest address that would otherwise be available.
-
- PMMAPIO (Protected Mode - Map Input/Output Device)
- Purpose: Create a logical address mapping for an input/output device which
- maps to a fixed physical memory address.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of MAPIO. See MAPIO for
- specifications.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 28
-
-
-
-
-
-
- 8. File Management
-
-
- XLIB file management procedures are low-level routines with powerful
- capabilities. These routines can load files to extended memory or save
- extended memory to files. They can read and write files either sequentially
- or randomly.
- All XLIB file management routines will receive and return values in a
- contiguous block of memory called a "file control block" (not to be confused
- with DOS file control blocks). The file control block must be located in
- conventional memory and must have the form presented in Table 5.
-
-
- Table 5: XLIB File Control Block Structure
- _____________________________________________________________________________
- Field Name Field Type Field Description
- ---------- ---------- -----------------
- CONDCODE DWORD Condition code from file operation
- FNAME BYTE[68] File path and name (zero terminated string)
- FHANDLE WORD File handle assigned by DOS
- FPTRMODE WORD File pointer mode
- FPTR DWORD File pointer
- BLKADR DWORD Memory source/destination address
- BLKSIZE DWORD Size of transfer block in bytes
- BUFADR DWORD Buffer address (conventional memory address)
- BUFSIZE WORD Buffer size in bytes
- CONTROL WORD Control word
- _____________________________________________________________________________
-
-
- CONDCODE is used to return error codes.
- FNAME is a zero-terminated ASCII string defining the file path and name.
- There cannot be more than 67 characters in this string, excluding the
- termination character.
- BLKADR and BLKSIZE define the source/destination memory block for the
- transfer. This block may be in either conventional or extended memory.
- BLKADR is a linear address.
- XLIB uses DOS to access the disk. DOS cannot read or write to extended
- memory; consequently, a conventional memory buffer must be set up for the DOS
- transfers. File management routines shift to protected mode to perform
- transfers between the buffer and the source/destination memory. BUFADR and
- BUFSIZE define the conventional memory buffer. BUFADR is a linear address.
- For fastest transfers, the memory block and the buffer should be DWORD
- aligned and should have sizes equal to an integer multiple of four.
- FPTR and FPTRMODE specify the file pointer setting to be used before
- transfers to or from the disk. FPTRMODE specifies how FPTR is to be
- interpreted. The following values are valid for FPTRMODE:
-
-
- FPTRMODE FPTR Interpretation
- 0 Unsigned offset from the beginning of the file
- 1 Signed offset from the current file pointer
- 2 Signed offset from the end of the file
- 3 FPTR is ignored. Use current file pointer (sequential mode)
-
-
-
- 29
-
-
-
-
-
-
- CONTROL is not used in the present version of XLIB. Set all bits in
- CONTROL to zero.
- In assembly language or C, the file control block would typically be
- defined by a structure. In BASIC, the file control block can be defined with
- a user defined type.
- Values are transferred to and from all file routines in EAX and in the
- file control block. All routines should be called with the linear address of
- the file control block in EAX. All routines return with two copies of the
- error code - one in EAX and one in the condition code of the file control
- block. A zero error code indicates successful execution.
- Since these routines perform disk operations, special precautions should
- be taken to ensure that parameters in the file control block are properly
- defined before performing calls. In particular, one should always make sure
- that the source/destination memory block and the conventional memory buffer
- are properly defined. A safe rule is to simply set the buffer size to zero
- because this forces XLIB to supply a buffer when opening or creating the file.
-
-
- Detailed Specifications
-
-
- XCREATE (Create File)
- Purpose: Create and open a new file of specified name in specified directory.
- CPU Mode: Real
- Registers at Call: EAX = linear address of file control block.
- Control Block at Call: FNAME = file path and name.
- Return Registers: EAX = error code. AX = XLIB error code. If a DOS error
- occurred, then the high word of EAX will be set to the DOS error code.
- Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
- FHANDLE = file handle assigned by DOS. If the procedure is called with
- BUFSIZE = 0, then XLIB will set BUFADR and BUFSIZE to its own internal buffer.
- Details:
- If the file already exists, then it will be truncated to zero length.
- The size and location of the internal buffer will depend upon how XLIB was
- initialized. If DPMI is active, then the buffer will be slightly larger than
- 2K; otherwise, the buffer will be slightly larger than 1K. The linear address
- and size of the buffer may be obtained from FILEBUFADR (DWORD), and
- FILEBUFSIZE (WORD) in DSEG.
- Files created by this routine will be given both read and write access.
- This routine uses INT 21H function 3CH to create the file.
-
- XOPEN (Open File)
- Purpose: Open existing file of specified name in specified directory.
- CPU Mode: Real
- Registers at Call: EAX = linear address of file control block.
- Control Block at Call: FNAME = file path and name.
- Return Registers: EAX = error code. AX = XLIB error code. If a DOS error
- occurred, then the high word of EAX will be set to the DOS error code.
- Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
- FHANDLE = file handle assigned by DOS. If the procedure is called with
- BUFSIZE = 0, then XLIB will set BUFADR and BUFSIZE to its own internal buffer.
-
-
-
-
-
-
- 30
-
-
-
-
-
-
- Details:
- The file is opened for both read and write access.
- The size and location of the internal buffer will depend upon how XLIB was
- initialized. If DPMI is active, then the buffer will be slightly larger than
- 2K; otherwise, the buffer will be slightly larger than 1K. The linear address
- and size of the buffer may be obtained from FILEBUFADR (DWORD), and
- FILEBUFSIZE (WORD) in DSEG.
- This routine uses INT 21H function 3DH to open the file.
-
- XCLOSE (Close File)
- Purpose: Close previously opened file.
- CPU Mode: Real
- Registers at Call: EAX = linear address of file control block.
- Control Block at Call: FHANDLE = file handle.
- Return Registers: EAX = error code. AX = XLIB error code. If a DOS error
- occurred, then the high word of EAX will be set to the DOS error code.
- Control Block at Return: CONDCODE = error code.
- Details: This routine uses INT 21H function 3EH to close the file.
-
- XSAVE (Save File)
- Purpose: Create file with contents equal to specified memory block.
- CPU Mode: Real
- Registers at Call: EAX = linear address of file control block.
- Control Block at Call: FNAME = file path and name. BLKADR/BLKSIZE = address
- and size of memory block to provide file contents. BUFADR/BUFSIZE = address
- and size of conventional memory buffer.
- Return Registers: EAX = error code. AX = XLIB error code. If a DOS error
- occurred, then the high word of EAX will be set to the DOS error code.
- Control Block at Return: CONDCODE = error code.
- Details:
- The file cannot already be open. The file is both created and closed by
- this routine.
- This routine will replace any previously existing file named FNAME.
- BLKADR/BLKSIZE may define a conventional memory block provided that this
- block is not overlapped by BUFADR/BUFSIZE.
- If this routine is called with BUFSIZE = 0, then XLIB will automatically
- set BUFADR and BUFSIZE to its own internal buffer.
- This routine transfers the source memory to the file through the buffer.
- Transfers from buffer to disk are accomplished with INT 21H function 40H.
-
- XLOAD (Load File)
- Purpose: Load file contents to specified memory block.
- CPU Mode: Real
- Registers at Call: EAX = linear address of file control block.
- Control Block at Call: FNAME = file path and name. BLKADR/BLKSIZE = address
- and size of memory block to receive file contents. BUFADR/BUFSIZE = address
- and size of conventional memory buffer.
- Return Registers: EAX = error code. AX = XLIB error code. If a DOS error
- occurred, then the high word of EAX will be set to the DOS error code.
- Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
- BLKSIZE = actual number of bytes transferred.
-
-
-
-
-
-
- 31
-
-
-
-
-
-
- Details:
- The file cannot already be open. The file is both opened and closed by
- this routine.
- The value of BLKSIZE as of call is interpreted as an upper limit on the
- number of bytes to transfer. The entire file is loaded provided that it does
- not contain more than BLKSIZE bytes.
- BLKADR/BLKSIZE may define a conventional memory block provided that this
- block is not overlapped by BUFADR/BUFSIZE.
- If this routine is called with BUFSIZE = 0, then XLIB will automatically
- set BUFADR and BUFSIZE to its own internal buffer.
- This routine uses INT 21H function 3FH to transfer the disk contents to the
- buffer. It then transfers the buffer contents to the destination memory.
-
- XWRITE (Write to File)
- Purpose: Write specified memory block to specified location in open file.
- CPU Mode: Real
- Registers at Call: EAX = linear address of file control block.
- Control Block at Call: FHANDLE = file handle. FPTR/FPTRMODE = file pointer
- setting for beginning of transfer. BLKADR/BLKSIZE = address and size of
- memory block to provide file contents. BUFADR/BUFSIZE = address and size of
- conventional memory buffer.
- Return Registers: EAX = error code. AX = XLIB error code. If a DOS error
- occurred, then the high word of EAX will be set to the DOS error code.
- Control Block at Return: CONDCODE = error code.
- Details:
- The file must be opened with XOPEN or XCREATE before using this routine.
- BLKADR/BLKSIZE may define a conventional memory block provided that this
- block is not overlapped by BUFADR/BUFSIZE.
- This routine uses INT 21H function 42H to set the file pointer. The source
- memory is then transferred through the buffer to disk. Transfers from buffer
- to disk are accomplished with INT 21H function 40H.
- Sequential transfers should set FPTRMODE = 3 for fastest execution.
-
- XREAD (Read From File)
- Purpose: Load specified memory block from specified location in open file.
- CPU Mode: Real
- Registers at Call: EAX = linear address of file control block.
- Control Block at Call: FHANDLE = file handle. FPTR/FPTRMODE = file pointer
- setting for beginning of transfer. BLKADR/BLKSIZE = address and size of
- memory block to receive file contents. BUFADR/BUFSIZE = address and size of
- conventional memory buffer.
- Return Registers: EAX = error code. AX = XLIB error code. If a DOS error
- occurred, then the high word of EAX will be set to the DOS error code.
- Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
- BLKSIZE = actual number of bytes transferred.
- Details:
- The file must be opened with XOPEN or XCREATE before using this routine.
- BLKADR/BLKSIZE may define a conventional memory block provided that this
- block is not overlapped by BUFADR/BUFSIZE.
- This routine uses INT 21H function 42H to set the file pointer. The file
- contents are then transferred to the destination memory through the buffer.
- The file contents are transferred to the buffer using INT 21H function 3FH.
- Sequential transfers should set FPTRMODE = 3 for fastest execution.
-
-
-
-
- 32
-
-
-
-
-
-
- PMXCREATE (Protected Mode - Create File)
- Purpose: Create and open a new file of specified name in specified directory.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of XCREATE. See XCREATE
- for details.
-
- PMXOPEN (Protected Mode - Open File)
- Purpose: Open an existing file of specified name in specified directory.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of XOPEN. See XOPEN for
- details.
-
- PMXCLOSE (Protected Mode - Close File)
- Purpose: Close previously opened file.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of XCLOSE. See XCLOSE
- for details.
-
- PMXSAVE (Protected Mode - Save File)
- Purpose: Create file with contents equal to specified memory block.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of XSAVE. See XSAVE for
- details.
-
- PMXLOAD (Protected Mode - Load File)
- Purpose: Load file contents to specified memory block.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of XLOAD. See XLOAD for
- details.
-
- PMXWRITE (Protected Mode - Write to File)
- Purpose: Write specified memory block to specified location in open file.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of XWRITE. See XWRITE
- for details.
-
- PMXREAD (Protected Mode - Read From File)
- Purpose: Load specified memory block from specified location in open file.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of XREAD. See XREAD for
- details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 33
-
-
-
-
-
-
- 9. Descriptor Management
-
-
- All selectors in Table 1 up to DGROUPSEL are used by XLIB procedures;
- consequently, the corresponding descriptors should never be changed. However,
- descriptors for the other selectors may be modified. XLIB includes a
- procedure called SETDESC (set descriptor) to facilitate such modifications. A
- second routine called PMSETDESC is the protected-mode version of SETDESC.
- Descriptors corresponding to the inline selectors should not be changed
- in programs which also use the inline mode-switch procedures.
- XLIB will also allow descriptors to be placed in the global descriptor
- table provided that DPMI is not being used. XLIB has no control over the
- global descriptor table under DPMI. The global descriptor table in XLIB
- begins at a public DWORD in DSEG called GDT. There are 48 descriptors in this
- table. The first 32 are either in use or are reserved by XLIB. Descriptors
- must be placed in the table by direct writes. The first available descriptor
- begins at DSEG offset OFFSET GDT + 100H. The selector values are simply the
- offsets from GDT. Hence, the selector value for the first available
- descriptor is 100H.
-
-
- Detailed Specifications
-
-
- SETDESC (Set Descriptor)
- Purpose: Change a descriptor in the local descriptor table.
- CPU Mode: Real
- Registers at Call: BX = selector. EDX:EAX = the new descriptor.
- Return Registers: EAX = error code. AX = XLIB error code. If DPMI is
- installed, then the high word of EAX will equal a DPMI 1.0 error code (if
- provided by host). EDX may be returned with some modifications to the access
- rights bits.
- Details:
- The access rights bits in EDX will be edited before installation of the
- descriptor. In particular: The application bit will be set to indicate an
- application segment (rather than a system segment). Reserved bits will be
- given proper settings. The descriptor privilege level will be set to the
- appropriate value. If the descriptor corresponds to a code segment, then the
- descriptor will also be marked as readable and nonconforming.
- Segment registers which are loaded with the old value of the descriptor
- will not necessarily be reloaded when the descriptor is changed.
-
- PMSETDESC (Protected Mode - Set Descriptor)
- Purpose: Change a descriptor in the local descriptor table.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of SETDESC. See SETDESC
- for details.
-
-
-
-
-
-
-
-
-
-
- 34
-
-
-
-
-
-
- 10. Using XLIB in High-Level Language Libraries
-
-
- The following program illustrates the usage of XLIB in libraries called
- from Microsoft BASIC 7.0. The library contains a protected-mode procedure
- which sums the elements in a single precision array created within BASIC. The
- general methodology here is recommended for developing assembly language
- libraries.
- Since BASIC cannot call a 32-bit segment, a real-mode interface procedure
- must be placed in a 16-bit segment to receive the BASIC call and then transfer
- execution to 32-bit protected mode. The interface procedure is call SUMARRAY
- while the 32-bit protected-mode procedure which actually sums the array
- elements is called SUMARRAY32.
- BASIC must pass certain arguments to the library procedures. These
- include the array address and the number of elements to be summed. These
- arguments could be passed on the stack; however, such approach proves awkward
- since the stack must be changed when entering protected mode. Consequently,
- BASIC places all arguments in a contiguous block of memory called a "control
- block," and then passes only the address of the control block to the library.
- BASIC constructs the control block with a user-defined type.
- The first four bytes of the control block are reserved for placement of
- error codes by the library procedures. Also, the address of the control block
- is placed in CCODEPTR so that any FPU exceptions will be signalled in the
- error code location as well. Were an FPU exception to occur, the FPU
- interrupt handler will immediately transfer control to EXITPM which will shift
- to real-mode, restore registers, and return control to the BASIC caller.
- The library also contains a real-mode function called LINADR which may be
- called by BASIC to convert segment addresses to linear addresses.
- An example of this same program for Microsoft C 7.0 is included in
- Appendix E. An example for Borland C is included in the files EXAMP3B.C and
- EXAMP3B.ASM.
-
-
- Example 3: Calling Protected-Mode Libraries From BASIC
- _____________________________________________________________________________
- +++++++++++++++++++++++++
- + ASSEMBLY CODE LIBRARY +
- +++++++++++++++++++++++++
-
-
- ;The following library should be combined with XLIB.LIB using the Microsoft
- ;LINK and LIB utilities. If BASIC is to be executed from the QBX environment,
- ;then a quick library must be loaded with the environment. See BASIC
- ;documentation for instructions.
-
-
- .MODEL LARGE,PASCAL
- .386P
-
- INCLUDE XLIB.INC
-
-
-
-
-
-
-
- 35
-
-
-
-
-
-
- CSEG SEGMENT PARA PUBLIC USE16 'CODE'
- ASSUME CS:CSEG, DS:DSEG
-
- ;Function to calculate linear address from segment address on stack.
- ;Returns linear address in DX:AX.
- LINADR PROC FAR PUBLIC,
- SEGADR:DWORD ;Segment address of variable
- XOR EAX,EAX ;Clear high words
- XOR EDX,EDX
- MOV AX,WORD PTR SEGADR[0]
- MOV DX,WORD PTR SEGADR[2]
- SHL EDX,4 ;Calculate linear address
- ADD EDX,EAX
- MOV AX,DX
- SHR EDX,16 ;Return linear address in DX:AX
- RET
- LINADR ENDP
-
- ;Structure defining control block for SUMARRAY.
- ARRAYDATA STRUCT
- CONDCODE DWORD 0 ;Condition code
- N DWORD 0 ;Number of elements to sum
- ADDRESS DWORD 0 ;Address of first element
- SUM DWORD 0 ;Sum of array elements
- ARRAYDATA ENDS
-
- ;Real-mode interface to SUMARRAY32. Segment address of control block having
- ;structure ARRAYDATA should be on the stack.
- SUMARRAY PROC FAR PUBLIC,
- CBSEGADR:DWORD ;Control block segment address
- PUSH DS
- PUSHW DSEG
- POP DS
- XOR EAX,EAX ;Clear high words
- XOR EDX,EDX
- MOV AX,WORD PTR CBSEGADR[2]
- MOV DX,WORD PTR CBSEGADR[0]
- SHL EAX,4 ;Calculate linear address
- ADD EAX,EDX
- MOV CCODEPTR,EAX ;Reset condition code address
- POP DS ;Pop calling DS
- PUSHD OFFSET SUMARRAY32
- CALL ENTERPM ;Execute SUMARRAY32 in protected
- RET
- SUMARRAY ENDP
-
- CSEG ENDS
-
-
-
-
-
-
-
-
-
-
- 36
-
-
-
-
-
-
- TSEG SEGMENT PARA PUBLIC USE32 'CODE'
- ASSUME CS:TSEG, SS:TSEG, DS:TSEG, ES:TSEG, FS:DSEG, GS:DGROUP
-
- ;Sum the elements of a single precision array. Array parameters are stored
- ;in a control block having structure of ARRAYDATA. The linear address of the
- ;control block is stored at CCODEPTR. An error code of -1 is returned in the
- ;condition code of the control block if the number of array elements is zero.
- ;XLIB places an error code in the control block if an FPU exception occurs
- ;while calculating the sum. This error code will have the FPU status word in
- ;the high word and the XLIB FPU error code in the low word. Observe that this
- ;routine will be called with DS = FLATDSEL (flat-model data descriptor) and
- ;FS = DSEGSEL (DSEG data descriptor).
- SUMARRAY32 PROC NEAR
- MOV EBX,FS:CCODEPTR ;Get control block
- MOV EDX,ARRAYDATA.ADDRESS[EBX] ;Get array address
- MOV ESI,ARRAYDATA.N[EBX] ;Get N
- SUB ESI,1
- JB NODATA ;Error: N = 0
- FLDZ ;Initialize sum
- SUMLOOP: FADD DWORD PTR [EDX+4*ESI]
- SUB ESI,1
- JAE SUMLOOP
- FSTP ARRAYDATA.SUM[EBX] ;Save sum
- RET
- NODATA: MOV ARRAYDATA.CONDCODE[EBX],-1 ;Record error code
- RET
- SUMARRAY32 ENDP
-
- TSEG ENDS
- END
-
-
- +++++++++++++++++++++
- + BASIC MAIN MODULE +
- +++++++++++++++++++++
-
-
- 'The following Microsoft BASIC 7.0 program should be linked with the above
- 'library. The BASIC program first initializes XLIB. Next, it creates a
- 'single precision array. A control block for SUMARRAY is then constructed
- 'and the call to SUMARRAY is executed. Finally, the condition code in the
- 'control block is inspected and results are printed.
-
- DEFINT A-Z
-
- 'Declare XLIB procedures
- DECLARE FUNCTION XLIBMEMREQ& ()
- DECLARE FUNCTION INITXLIB& ()
- DECLARE FUNCTION XLIBCONFIG% ()
-
- 'Declare procedures in the library linked with XLIB
- DECLARE FUNCTION LINADR& (SEG VARIABLE AS ANY)
- DECLARE SUB SUMARRAY (SEG VARIABLE AS ANY)
-
-
-
-
- 37
-
-
-
-
-
-
- 'Structure for the control block
- TYPE ARRAYDATA
- CONDCODE AS LONG 'Location to receive any error codes
- N AS LONG 'Number of elements to be summed
- ADDRESS AS LONG 'Linear address of the array
- SUM AS SINGLE 'Location for array sum
- END TYPE
-
- 'Check XLIBCONFIG to see if XLIB has already been initialized. If not then
- 'call XLIBMEMREQ to find amount of conventional memory needed by XLIB and
- 'release at least this amount with the BASIC SETMEM function. XLIBMEMREQ
- 'returns with sign bit of DX set if an error occurred. The error is then
- 'identified by AX. XLIB will not be terminated upon completion of this
- 'program in the Microsoft QBX environment; therefore, initialization is
- 'required only once within the environment.
- IF XLIBCONFIG = 0 THEN
- TEMP& = XLIBMEMREQ
- IF TEMP& >= 0& THEN
- IF TEMP& > 0 THEN TEMP& = SETMEM(-TEMP& - 16&)
- TEMP& = INITXLIB 'INITXLIB error code returned in TEMP&
- ELSE
- TEMP& = TEMP& AND &H7FFFFFFF 'Mask sign bit to leave error code only
- END IF
- IF TEMP& THEN
- PRINT "Library initialization error: "; HEX$(TEMP&)
- END
- END IF
- END IF
-
- DIM A(100) AS SINGLE
- DIM AD AS ARRAYDATA
-
- FOR I = 0 TO 100 'Assign numbers to array
- A(I) = I
- NEXT I
-
- AD.CONDCODE = 0& 'Clear the error code
- AD.N = 50& 'Sum first 50 elements
- AD.ADDRESS = LINADR(A(0)) 'Calculate and record linear address of A(0)
-
- CALL SUMARRAY(AD)
-
- IF AD.CONDCODE THEN
- PRINT "Error: ";HEX$(AD.CONDCODE)
- ELSE
- PRINT "Sum: ";AD.SUM 'Should equal 1225
- ENDIF
-
- END
- _____________________________________________________________________________
-
-
-
-
-
-
-
- 38
-
-
-
-
-
-
- 11. Using XLIBE for Debugging and Exception Trapping
-
-
- XLIBE.LIB contains all of the functions of XLIB.LIB plus other functions
- designed for debugging and exception trapping. XLIBE.LIB consumes more memory
- than XLIB.LIB; consequently, the programmer may wish to use the former for
- program development and the latter for release versions. The same header and
- include files are used for both libraries.
- Typically, a VCPI server or a DPMI host will be accompanied with
- exception handlers. However, because such handlers do not have specific
- knowledge of the programs they will be serving, they typically do a relatively
- poor job of restoring machine state after an exception occurs. As a
- consequence, reboot is often necessary. Also, such handlers generally do a
- poor job of reporting the machine state as of the exception; consequently,
- they are of limited usefulness toward debugging programs.
- XLIBE.LIB contains protected-mode handlers for all CPU exceptions. These
- handlers will generally be able to perform complete cleanup after an exception
- occurs thereby eliminating the need for reboot. The state of the machine as
- of the exception is thoroughly reported; therefore, the programmer should be
- able to quickly identify the source of the exception.
- If DPMI 1.0 is being used, then XLIBE can also trap exceptions occurring
- in real mode. This ability makes XLIBE useful even to programmers who would
- otherwise be writing exclusively real-mode code.
- All of the additional features of XLIBE are activated by default. Once
- the call to INITXLIB has been successfully executed, protected-mode exception
- trapping will be enabled, and real-mode exception trapping will be enabled
- provided that DPMI 1.0 is installed. The default behavior of XLIBE can
- however be modified by IFLAGS, as described below.
- Two CPU exceptions are specifically designed for debugging. These are
- exception #1 and exception #3. Exception #1 is used for debug data
- breakpoints. This exception is generated with any attempt to access
- predefined addresses in either data or code. As many as four data breakpoint
- addresses may be defined with use of XLIBE procedures. Exception #3 is
- generated by the INT 3 instruction. This instruction may be inserted in the
- code at any point where the programmer wishes to inspect the processor state.
- The XLIBE handlers for both exceptions are designed to allow the programmer
- the option of resuming execution after the exceptions are reported.
- One of the notorious flaws in the IBM AT architecture is the manner in
- which hardware interrupts are programmed. Hardware interrupt requests (IRQs)
- 0-7 are assigned to interrupt vectors 8-15. Unfortunately, these same
- interrupt vectors are used for CPU exceptions. Consequently, when an
- interrupt occurs through one of these vectors, it is sometimes difficult to
- determine if the interrupt was generated by external hardware or by the CPU.
- For example, an INT 8 could be generated either by the system timer or by a
- double fault exception. The INT 8 handler should, if possible, make a
- determination of the source of the interrupt before servicing it. However, an
- easier and more reliable solution is to correct the problem at its root by
- remapping hardware interrupts to different vectors. The approach taken by
- XLIBE will depend upon the active protected-mode host/server.
- If DPMI is not installed, then the default behavior of XLIBE is to remap
- hardware interrupts during initialization. By default, XLIBE remaps IRQs 0-8
- to vectors 50H-57H and IRQs 9-15 to vectors 58H-5FH. These vectors may
- however be changed by the programmer. The target vectors are contained in
- PIC1BASEINT (programmable interrupt controller #1 base interrupt) and
-
-
-
- 39
-
-
-
-
-
-
- PIC2BASINT. Both variables are BYTE locations in DSEG. They should be
- changed before calling INITXLIB. The base interrupt vectors must be evenly
- divisible by eight.
- IRQs 9-15 are traditionally assigned to vectors 70H-77H. This mapping
- poses no problem because there is no conflict with CPU exceptions at these
- addresses. XLIB remaps to 50H-57H simply because these addresses have been
- used in other protected-mode software (e.g. DESQview and OS/2 1.x).
- XLIBE will not attempt to remap hardware interrupts if it discovers that
- the mappings have already been changed from their conventional locations.
- INITXLIB terminates with an error code in such cases.
- When XLIBE remaps hardware interrupts, it also installs real-mode
- handlers at the new hardware interrupt vectors. These handlers simply
- transfer execution to the addresses at the old vectors. This approach ensures
- complete compatibility with any resident software which may expect
- conventional hardware interrupt mappings. Accordingly, the programmer should
- install real-mode hardware interrupt handlers in usual fashion. For example,
- a timer-tick interrupt handler should be installed at INT 8. However,
- protected-mode handlers for these interrupts should be installed at the new
- vectors. The new vectors should be read from IRQ0INTNO and IRQ8INTNO after
- calling INITXLIB.
- The approach taken under DPMI is somewhat different. The DPMI host will
- expect conventional hardware interrupt mappings. The host will always
- immediately receive control after interrupts. The host will identify the
- interrupt as being a software interrupt, hardware interrupt, or CPU exception.
- It will then transfer control to the appropriate handler. Consequently, it is
- not necessary for XLIBE to remap hardware interrupts under DPMI. The values
- in PIC1BASEINT and PIC2BASEINT are ignored in this case. After the call to
- INITXLIB, IRQ0INTNO will equal 08H and IRQ8INTNO will equal 70H.
- XLIBE allows a high degree of control over exception trapping behavior.
- Three bits in IFLAGS are designed for this purpose. Bit 1 can be set to
- disable all exception trapping and remap of hardware interrupts. XLIBE is
- functionally equivalent to XLIB when this bit is set. Bit 2 may be set to
- disable real-mode exception trapping. This bit is meaningful only when DPMI
- 1.0 is installed and when bit 1 is clear. Bit 3 may be set to prevent XLIBE
- from accessing the CPU debug registers. This bit is meaningful only if bit 1
- is clear. The programmer may wish to set this bit if a debugger is being
- used. All of these bits are clear by default.
- The programmer may selectively install exception handlers by altering the
- bit settings in CPUINTFLAGS (CPU interrupt flags). CPUINTFLAGS is a public
- DWORD in DSEG. A set bit enables installation of the the corresponding
- exception handler. The default value of CPUINTFLAGS is FFFBH. This enables
- installation of handlers for all exceptions apart from exception #2 (non-
- maskable interrupt), exception #16 (FPU exception), and exception #17
- (alignment check). FPU exceptions are handled in the AT architecture through
- a hardware interrupt (IRQ 13) rather than exception #16. Alignment is seldom
- demanded in the AT architecture.
- When an exception occurs, the XLIBE exception handlers print useful
- information about the exception in a screen report. Appendix H contains
- instructions for interpreting this information and for identification of the
- source of the exception.
-
-
-
-
-
-
-
- 40
-
-
-
-
-
-
- Detailed Specifications
-
-
- The procedures presented in this section are contained in XLIBE.LIB but not
- in XLIB.LIB.
-
-
- SETWATCH (Set Watchpoint)
- Purpose: Set a data breakpoint for generation of exception #1.
- CPU Mode: Real
- Registers at Call: EAX = linear address of breakpoint. DL = length of
- breakpoint in bytes. DH = type of breakpoint. DL must equal 1, 2, or 4.
- Alternative values for DH are: 0 - execution breakpoint, 1 - write
- breakpoint, and 2 - read/write breakpoint.
- Return Registers: EAX = error code. AX = XLIB error code. If DPMI is
- installed, then the high word of EAX will equal a DPMI 1.0 error code (if
- provided by host). EBX = handle for releasing the breakpoint.
- Details:
- The linear address supplied in EAX must have alignment equal to the length
- supplied in DL.
- If an execute breakpoint is specified (DH = 0), then the length must equal
- 1 (DL = 1).
- Exception #1 is generated upon access of any byte within the breakpoint
- field.
- Up to four data breakpoints may be simultaneously defined.
- Under all protected-mode configurations except DPMI .9, the handle will
- equal the number of the assigned debug breakpoint register. The DPMI .9
- specifications have no requirements for handle values.
- The exception report will print the value of DR6 (debug status register).
- This register may be examined to determine which breakpoint generated the
- exception. The lowest four bits contain this information. Set bits indicate
- that the corresponding breakpoint condition is satisfied.
- The presented value for DR6 is not relevant under DPMI .9. Under DPMI 1.0,
- the presented value is for a virtual DR6 and will not have exact
- correspondence with the actual DR6. In particular, bits 15 and 13 (BT and BD
- bits) are undefined. Under XLIB and VCPI mode switching, the actual DR6 is
- presented.
- If the programmer chooses to resume execution from the exception handler,
- then DR6 will be cleared before resumption.
- Breakpoints are globally enabled under XLIB and VCPI mode switching.
- Breakpoint visibility under DPMI will depend upon the host.
- Under XLIB or VCPI mode switching, exact breakpoint matching is used for
- 386 processors. This means that the reported CS:EIP points to the instruction
- which generated the exception rather than the instruction after. Such
- behavior is always the case with 486 and Pentium processors. Trapping
- behavior under DPMI will depend upon the host.
-
- FREEWATCH (Free Watchpoint)
- Purpose: Release previously allocated debug data breakpoint.
- CPU Mode: Real
- Registers at Call: EAX = watchpoint handle.
- Return Registers: EAX = error code. AX = XLIB error code. If DPMI is
- installed, then the high word of EAX will equal a DPMI 1.0 error code (if
- provided by host).
-
-
-
- 41
-
-
-
-
-
-
- RESETWATCH (Reset Watchpoints)
- Purpose: Release all previously allocated debug data breakpoints.
- CPU Mode: Real
- Registers at Call: None
- Return Registers: EAX = error code. AX = XLIB error code. If DPMI is
- installed, then the high word of EAX will equal a DPMI 1.0 error code (if
- provided by host).
- Details: Either RESETWATCH or PMRESETWATCH will be called automatically by
- XLIBE upon program termination.
-
- PMSETWATCH (Protected Mode - Set Watchpoint)
- Purpose: Set a data breakpoint for generation of exception #1.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of SETWATCH. See
- SETWATCH for details.
-
- PMFREEWATCH (Protected Mode - Free Watchpoint)
- Purpose: Release previously allocated debug data breakpoint.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of FREEWATCH. See
- FREEWATCH for details.
-
- PMRESETWATCH (Protected Mode - Reset Watchpoints)
- Purpose: Release all previously allocated debug data breakpoints.
- CPU Mode: Protected
- Details: This routine is the protected-mode version of RESETWATCH. See
- RESETWATCH for details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 42
-
-
-
-
-
-
- Appendix A: Description of XLIB Public Data
-
-
- The following is a summary of most public symbols for XLIB data. These
- symbols pertain to segment DSEG except where otherwise noted. This summary
- excludes many of the symbols presented in tables one through four. All XLIB
- symbols conform to the PASCAL naming convention.
-
- Symbol: CALL32PTR (CALL32 Pointer)
- Symbol Type: DWORD
- Default Setting: Far 16-bit protected-mode address of CALL32 procedure
- Description: This location is a pointer to the CALL32 procedure and is
- included to facilitate intersegment calls. The contents of the location
- should not be changed.
-
- Symbols: CCODEPTR/CCODE (Condition Code Pointer/Condition Code)
- Symbol Types: DWORD/DWORD
- Default Settings: CCODEPTR = linear address of CCODE. CCODE = 0.
- Descriptions: XLIB interrupt handlers will place flags in the condition code
- to signal the occurrence of the interrupt. Flags are placed for FPU
- exceptions and hot key presses. CCODEPTR initially contains the linear
- address of CCODE. CCODEPTR may be changed by the user, but must point to a
- DWORD in conventional memory. The user is responsible for initializing the
- condition code.
-
- Symbol: CPUINTFLAGS (CPU Interrupt Flags)
- Symbol Type: DWORD
- Default Setting: FFFBH
- Description: One can selectively enable installation of CPU exception
- handlers in XLIBE by appropriately setting the bits in CPUINTFLAGS. A set bit
- enables the corresponding exception. By default, installation of handlers for
- all exceptions is enabled except for nonmaskable interrupts, FPU exceptions,
- and alignment checks. FPU exceptions are handled through IRQ 13 rather than
- the CPU. Alignment checks are not typically made in the IBM AT architecture.
- The settings in CPUINTFLAGS have no effect on XLIB.
-
- Symbol: CSDSEGSEL (Code Segment Copy of DSEGSEL)
- Symbol Type: WORD
- Default Setting: Varies with operating environment
- Description: This is a WORD in TSEG containing the value of the DSEG
- selector. Since XLIB selector values are not constant, they must be read from
- memory locations. Such locations are placed in segment DSEG (see Table 1);
- however, one must know the DSEG selector to read these locations. Therefore,
- a copy of the DSEG selector is placed in the code segment where it can always
- be found.
-
- Symbols: CSEGVAL, TSEGVAL, DSEGVAL, DGROUPVAL (Segment Values)
- Symbol Types: WORD
- Default Settings: CSEG, TSEG, DSEG, DGROUP
- Descriptions: These are memory locations initialized to the respective
- segment values. Code in TSEG should not contain segment constants since DOS
- may not be able to handle them in relocation edits. Read these locations to
- get segment values. User segments should be handled the same way. These
- locations should not be changed.
-
-
-
- 43
-
-
-
-
-
-
- Symbols: FILEBUFADR/FILEBUFSIZE (File Buffer Specifications)
- Symbol Types: DWORD/WORD
- Default Settings: Varies with operating environment
- Descriptions: FILEBUFADR contains the linear address of the internal file
- buffer in XLIB. FILEBUFSIZE contains the size of the buffer in bytes. This
- buffer is used only by the file management routines. The size and location of
- the buffer will depend upon the operating environment. If DPMI is active,
- then the buffer will be slightly larger than 2K; it is otherwise slightly
- larger than 1K. These location should be read only after initialization.
-
- Symbol: FPUCW (Floating Point Unit Control Word)
- Symbol Type: WORD
- Default Setting: 0332H
- Description: FPUCW is optionally loaded to the FPU control word by CALLPM and
- ENTERPM. The default sets rounding control to nearest, precision control to
- 64 bits, and unmasks exceptions for overflow, zero divide, and invalid
- operations. Exceptions for underflow, precision, and denormalized operations
- are masked, and are therefore handled internally by the FPU. Set bit 2 of
- OFLAGS to enable FPU save/restore and load of FPUCW.
-
- Symbol: GDT (Global Descriptor Table)
- Symbol Type: DWORD
- Default Setting: Not applicable
- Description: GDT is the first DWORD in the global descriptor table. This
- table contains 40 descriptors. The last sixteen are available for use.
- Descriptors must be placed in the table by direct writes. The first available
- descriptor begins at DSEG offset OFFSET GDT + 100H. The selector values are
- simply the offsets from GDT. Hence, the selector value for the first
- descriptor is 100H. The global descriptor table should not be used under
- DPMI.
-
- Symbol: HOTKEY (Hot Key)
- Symbol Type: WORD
- Default Setting: 0H
- Description: HOTKEY specifies the hot key for the keyboard interrupt handler.
- The low byte of HOTKEY specifies the scan code for the key. The upper byte
- specifies the state of the shift keys. Bit 8 specifies SHIFT; bit 9 specifies
- CTLR, and bit 10 specifies ALT. Set bits mean that the designated key must be
- pressed. All other bits are ignored. When the hot key is pressed, the XLIB
- keyboard interrupt handler will record the hot key flag at the DWORD whose
- linear address is stored at CCODEPTR. The default setting for HOTKEY is 0.
- This setting effectively disables hot key detection since no key has a zero
- scan code.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 44
-
-
-
-
-
-
- Symbol: IFLAGS (Initialization Flags)
- Symbol Type: WORD
- Default Setting: 0200
- Description: IFLAGS is used by INITXLIB to control the initialization
- process.
- Bit 0 determines DPMI/VCPI priority in the event that both interfaces are
- present. If this bit is clear then DPMI will be installed; otherwise, VCPI
- will be installed.
- Bit 1 disables protected-mode exception trapping in XLIBE. It also
- disables remap of hardware interrupts. XLIBE is functionally equivalent to
- XLIB when this bit is set. The bit does not effect XLIB.
- Bit 2 disables real-mode exception trapping in XLIBE. This bit is
- meaningful only if DPMI 1.0 is installed and if bit 1 of IFLAGS is clear. The
- bit does not effect XLIB.
- Bit 3 disables XLIBE usage of debug registers. This bit is meaningful only
- if bit 1 of IFLAGS is clear. The bit does not effect XLIB.
- The upper byte of IFLAGS determines the strategy to be used by INITXLIB if
- conventional memory is to be allocated. The possible strategies are presented
- in Table 2. The default causes XLIB to allocate from the highest available
- address in conventional memory.
-
- Symbol: INLINERMPTR (INLINERM Pointer)
- Symbol Type: DWORD
- Default Setting: Far 16-bit protected-mode address of INLINERM procedure
- Description: This location is a pointer to the INLINERM procedure and is
- included to facilitate intersegment calls. The contents of the location
- should not be changed.
-
- Symbols: IRQ0INTNO/IRQ8INTNO (IRQ X Interrupt Number)
- Symbol Types: BYTE/BYTE
- Default Settings: Varies with operating environment
- Descriptions: Specifies the interrupt number assigned to IRQ X. IRQs 0
- through 7 and IRQs 8 through 15 are assigned to contiguous interrupt numbers.
- These locations are valid only after call to INITXLIB. Typically, IRQ 0 is
- assigned to interrupt 8, and IRQ 8 is assigned to interrupt 70H; however,
- these assignments may have been changed by system software or by XLIBE.
-
- Symbol: OFLAGS (Operation Flags)
- Symbol Type: WORD
- Default Setting: Varies with operating environment
- Description: OFLAGS controls post-initialization operation of XLIB.
- Setting bit 0 enables XLIB hardware interrupt handlers. These handlers
- will continue to receive interrupts but will always cascade them when the bit
- is clear. XLIB sets this bit only at calls to CALLPM and ENTERPM and then
- clears the bit upon return. When the bit is clear, hot key detection is
- disabled, and the XLIB FPU interrupt handler is disabled.
- Setting bit 1 causes all FPU interrupts to be cascaded to the inherited
- real-mode interrupt handler. This bit is initialized by INITXLIB. It is set
- if no FPU is present; it is otherwise cleared.
- Setting bit 2 enables FPU save/restore in CALLPM and ENTERPM. Setting this
- bit also causes load of FPUCW to the FPU control word. The bit is clear by
- default.
-
-
-
-
-
- 45
-
-
-
-
-
-
- Symbol: PAGESIZE (Page Size)
- Symbol Type: DWORD
- Default Setting: Varies with operating environment
- Description: This memory location contains the minimum unit (in bytes) for
- extended memory allocation. PAGESIZE is initialized by INITXLIB. It will
- contain 4096 for VCPI, 1024 for XMS, and 16 for clean configurations. Values
- can vary under DPMI but will typically equal 4096. Extended memory requests
- are rounded up to the nearest integer multiple of PAGESIZE. Extended memory
- blocks will be PAGESIZE aligned.
-
- Symbols: PIC1BASEINT/PIC2BASEINT (Programmable Interrupt Controller X Base
- Interrupt)
- Symbol Types: BYTE/BYTE
- Default Settings: 50H/58H
- Description: If exception trapping is enabled under XLIBE and if XLIB or VCPI
- mode switching is to be used, then hardware interrupts will be remapped during
- initialization. PIC1BASEINT specifies the starting interrupt number for the
- master programmable interrupt controller (IRQs 0-7). PIC2BASEINT specifies
- the starting interrupt number for the slave controller (IRQs 8-15). These
- variables should be set to the desired values before the call to INITXLIB.
- Both interrupt numbers must be evenly divisible by eight. These variables
- have no effect on XLIB.
-
- Symbols: PMDS, PMES, PMFS, PMGS (Protected-Mode Segments)
- Symbol Types: WORD
- Default Settings: FLATDSEL, TSEGDSEL, DSEGSEL, DGROUPSEL
- Descriptions: These memory locations are loaded to data segment registers by
- CALLPM and ENTERPM before transferring control to the protected-mode target.
- These locations are respectively loaded to DS, ES, FS, and GS. The contents
- of these locations may be changed to any legal selectors after the call to
- INITXLIB.
-
- Symbols: RMDS, RMES (Real-Mode Segments)
- Symbol Types: WORD
- Default Settings: DGROUP, DSEG
- Descriptions: These memory locations are loaded to data segment registers by
- CALLRM before transferring control to the real-mode target. These locations
- are respectively loaded to DS and ES. The contents of these locations may be
- changed if desired.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 46
-
-
-
-
-
-
- Appendix B: XLIB Error Codes
-
-
- XLIB error codes are always returned in AX. In many cases, the high word
- of EAX will be returned with specific information about the error, such as
- XMS, DPMI, or DOS error codes.
- Although error codes are not provided in the DPMI .9 specification, many
- DPMI .9 hosts do return DPMI 1.0 error codes. DPMI 1.0 error codes may in
- fact be DOS error codes returned to the DPMI host by DOS. If the sign bit
- (bit 15) of the error code is clear, then the error code was issued by DOS.
- Error codes have been changed from earlier versions of XLIB.
-
- Condition Code Flags
- 01H FPU exception
- 02H Hot key pressed
-
- General Errors
- 10H Unable to identify operating environment
- 11H DOS memory allocation failure
- 12H DOS memory release error
- 13H Failed to enable A20
- 14H Insufficient logical address space
- 15H Insufficient number of handles
- 16H Bad handle
- 17H Bad selector
- 18H Bad address
- 19H Unable to create file
- 1AH Unable to open file
- 1BH Unable to read file
- 1CH Unable to write file
- 1DH Unable to set file pointer
- 1EH Unable to close file
- 1FH Disk full
- 20H Unable to remap hardware interrupts
- 21H Bad debug data watchpoint specification
-
- Errors Occurring Under DPMI (See Appendix C for codes returned by DPMI)
- 30H Protected mode initialization failure
- 31H Descriptor allocation error
- 32H Descriptor installation error
- 33H Unable to switch protected mode interrupt vector
- 34H Insufficient extended memory error
- 35H Extended memory allocation error
- 36H Extended memory release error
- 37H DOS memory allocation error
- 38H DOS memory release error
- 39H Unable to set descriptor base address
- 3AH Physical address mapping error
- 3BH Unable to get protected-mode exception vector
- 3CH Unable to set protected-mode exception vector
- 3DH Unable to get real-mode exception vector
- 3EH Unable to set real-mode exception vector
- 3FH Unable to set debug data breakpoint
- 40H Unable to release debug data breakpoint
-
-
-
- 47
-
-
-
-
-
-
- Errors Occurring Under XMS (See Appendix D for codes returned by XMS)
- 50H Unable to enable A20
- 51H Unable to measure available extended memory
- 52H Insufficient extended memory error
- 53H Extended memory allocation error
- 54H Unable to lock extended memory
- 55H Unable to unlock extended memory
- 56H Extended memory release error
-
- Errors Occurring Under VCPI
- 60H Error in determining protected mode entry point
- 61H Unable to determine physical address of DOS memory page
- 62H Unable to determine hardware interrupt mappings
- 63H Insufficient extended memory error
- 64H Unable to determine number of free extended memory pages
- 65H Extended memory allocation error
- 66H Extended memory release error
- 67H Hardware interrupt remap error
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 48
-
-
-
-
-
-
- Appendix C: DPMI 1.0 Error Codes
-
-
- DPMI 1.0 error codes may in fact be DOS error codes returned to the DPMI
- host by DOS. If the sign bit (bit 15) of the error code is clear, then the
- error code was issued by DOS.
-
-
- Number Explanation
- 8001H Unsupported function
- 8002H Invalid state for requested operation
- 8003H System integrity would be endangered
- 8004H Deadlock situation detected by host
- 8005H Serialization request cancelled
- 8010H Resource unavailable
- 8011H Host unable to allocate descriptor
- 8012H Linear memory unavailable
- 8013H Physical memory unavailable
- 8014H Backing store unavailable
- 8015H Callback specifications cannot be allocated
- 8016H Cannot allocate handle
- 8017H Lock count limits exceeded
- 8018H Resource owned exclusively by another client
- 8019H Resource already shared by another client
- 8021H Invalid value
- 8022H Invalid selector
- 8023H Invalid handle
- 8024H Invalid callback
- 8025H Invalid linear address
- 8026H Request not supported by hardware
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 49
-
-
-
-
-
-
- Appendix D: XMS Error Codes
-
-
- Number Explanation
- 80H Function not implemented
- 81H VDISK was detected
- 82H An A20 error occurred
- 8EH General driver error
- 8FH Unrecoverable driver error
- 90H HMA does not exist
- 91H HMA is already in use
- 92H Attempt to allocate less than HMAMIN of HMA
- 93H HMA is not allocated
- 94H A20 is still enabled
- A0H All extended memory is allocated
- A1H All available handles are allocated
- A2H Invalid handle
- A3H Source handle is invalid
- A4H Source offset is invalid
- A5H Destination handle is invalid
- A6H Destination offset is invalid
- A7H Length is invalid
- A8H Move has an invalid overlap
- A9H Parity error
- AAH Block is not locked
- ABH Block is locked
- ACH Block lock count overflow
- ADH Lock failed
- B0H Only a smaller upper memory block (UMB) is available
- B1H No UMB's are available
- B2H UMB segment number is invalid
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 50
-
-
-
-
-
-
- Appendix E: Calling Protected-Mode Libraries From C
-
-
- This appendix contains a C version of the BASIC program presented in
- Example 3. Microsoft C version 7.0 is used to create a float array. C then
- calls a protected-mode assembly language procedure in a library to sum the
- elements of the array. The assembly language library in Example 3 will work
- here with no modification. C calls a real-mode procedure called SUMARRAY.
- This procedure then transfers control to a 32-bit protected-mode procedure
- called SUMARRAY32. The latter procedure performs the actual calculations.
- Parameters defining the array are placed in a contiguous block of memory
- defined by a C structure. C passes the address of this structure to the
- library. The first four bytes in the structure are reserved for error codes.
- The linear address of the structure is placed in CCODEPTR so that any FPU
- exceptions will be recorded by the FPU interrupt handler in the error code
- location. The SUMARRAY32 procedure will also record an error if the parameter
- defining the number of elements to be summed is zero.
- The C code is somewhat simpler than the corresponding BASIC code because
- conventional memory does not have to be released prior to calling INITXLIB.
- This follows because C does not claim all DOS memory as does BASIC.
- C is more powerful than BASIC in that it can access data under external
- symbols whereas BASIC cannot. Access to XLIB public data is made possible in
- C by including the header file called XLIB.H. This file makes all XLIB public
- data and public real-mode procedures visible to C. It also contains
- declarations which adapt the PASCAL conventions of XLIB.
- A Borland version of this program and of the accompanying library may be
- found in the files EXAMP3B.C and EXAMP3B.ASM.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 51
-
-
-
-
-
-
- _____________________________________________________________________________
- /*The following Microsoft C 7.0 program should be linked with the assembly
- language library in Example 3. Combine the library with XLIB.LIB using the
- Microsoft LIB utility. The C program first initializes XLIB. Next, it
- creates a float array. A control block for SUMARRAY is then constructed
- and the call to SUMARRAY is executed. Finally, the condition code in the
- control block is inspected and results are printed.*/
-
- #include <stdio.h>
- #include <xlib.h>
-
- extern long __far __pascal LINADR(void __far *ptr);
- extern void __far __pascal SUMARRAY(void __far *ptr);
-
- struct arraydata /*Structure for passing arguments to SUMARRAY*/
- {
- long condcode;
- long n;
- long address;
- float sum;
- } ad;
-
- main()
- {
- int i;
- long temp;
- float a[101];
- temp = INITXLIB(); /*Initialize XLIB*/
- if (temp != 0) /*See if an error occurred*/
- {
- printf("Initialization Error: %lX\n",temp);
- return 0;
- }
-
- for(i = 0; i <= 100; i++) /*Initialize a[]*/
- a[i] = i;
-
- ad.condcode = 0; /*Initialize the condition code*/
- ad.n = 50; /*Will sum the first 50 elements in a[]*/
- ad.address = LINADR(a); /*Compute and record linear address of a[]*/
-
- SUMARRAY(&ad); /*Sum the array elements*/
- if (ad.condcode != 0) /*See if an FPU error occurred*/
- {
- printf("Error: %lX\n",ad.condcode);
- return 0;
- }
- printf("Sum: %f\n",ad.sum); /*The sum should be 1225*/
- }
- _____________________________________________________________________________
-
-
-
-
-
-
-
- 52
-
-
-
-
-
-
- Appendix F: Technical Support
-
-
- Technical support for XLIB is provided to both registered and
- unregistered users; however, the registration fee is $60 per copy for those
- who have used technical support or who intend to use it. The additional
- charges will be waived for those who discover bugs in the XLIB libraries.
- Before contacting TechniLib with a problem, the following steps should be
- taken:
-
- 1) Ensure that your own program always checks the error codes returned by XLIB
- procedures. These codes will likely resolve the problem. If not, then make
- note of the code.
-
- 2) Attempt to execute your program under DPMI, VCPI, and in the absence of
- both. If the problem relates to memory management, then also attempt to
- execute your program in the presence of XMS but in the absence of DPMI and
- VCPI, then attempt to execute in the absence of all three interfaces. It will
- generally be found that the problem occurs only under a specific interface.
- If so, then note the interface under which the problem occurs.
-
- 3) If the problem occurs only under one interface, then attempt to execute
- your program under different implementations of the interface. For example, a
- DPMI host is contained in Windows 3.1, 386MAX, QDPMI, and OS/2 2.x. Try
- executing your program under each host and make note of the results. Problems
- occurring only under one host are generally indicative of bugs in the host
- rather than XLIB.
-
- 4) Try different options on your memory management software.
-
- 5) Try different options on your compiler, assembler, and linker. It is
- sometimes the case that code is not processed properly under some options.
-
- 6) If the problem results in a processor exception, then run the program with
- one of the exception trapping libraries (e.g. XLIBE.LIB) and make note of the
- report that is presented as of the exception.
-
- Technical support is available at:
-
- Dr. David Pyles
- TechniLib Company
- P.O. Box 6818
- Jackson, Ms. 39282
- (601) 372-7433
-
- Problems may also be reported by CompuServe mail to CIS ID: 74730,167.
-
-
-
-
-
-
-
-
-
-
-
- 53
-
-
-
-
-
-
- Appendix G: The SWITCHPM and SWITCHRM Procedures
-
-
- SWITCHPM and SWITCHRM are the primitive mode-switch routines used by
- nearly all XLIB procedures requiring execution in both real and protected
- modes. They are made public for users who need to perform mode switching
- tasks not otherwise provided by XLIB. These routines do not conform to the
- general conventions followed by other XLIB procedures; consequently, they are
- presented in an appendix.
- In some cases the programmer may deem CALLPM and ENTERPM to be too slow
- for a particular mode switching task. Both procedures consume time in storing
- register state and in making other preparations for abrupt or unpredictable
- exits from protected mode (via jumps to RETPM/EXITPM or FPU exceptions).
- SWITCHPM and SWITCHRM perform mode switches in minimum CPU time.
- The greatest limitation to CALLPM/ENTERPM is that these procedures are
- not reentrant; consequently, calls to these procedures cannot be nested. This
- limitation could prove a problem if the programmer needed to perform a mode
- switch within a real-mode interrupt handler. If the interrupt originated in
- protected mode, then CALLPM/ENTERPM could not be used to perform the mode
- switch. Since interrupt handlers generally should not make assumptions about
- machine state, CALLPM/ENTERPM generally should not be used within such
- handlers. Use SWITCHPM and SWITCHRM instead.
- A less likely situation occurs where the programmer first enters
- protected mode via CALLPM/ENTERPM then executes real-mode code with CALLRM.
- The real-mode code could not then switch to protected mode with CALLPM/ENTERPM
- since this would be nesting the procedures.
- Both SWITCHPM and SWITCHRM are near procedures in CSEG; therefore, they
- must be called from this segment. SWITCHPM returns to the caller in 16-bit
- protected mode. SWITCHRM returns to the caller in real mode. Both procedures
- must be called with a stack in DSEG.
- SWITCHPM returns with CS = CSEGSEL and with all other segments equal to
- DSEGSEL. All other registers, including the status flags, are preserved.
- SWITCHRM returns with CS = CSEG and with SS, DS, and ES set to DSEG. FS
- and GS are undefined. All other registers, including the status flags, are
- preserved.
- Each interrupt handler using SWITCHPM/SWITCHRM should have its own unique
- stack in DSEG in the event that nested interrupts occurred.
- After switching to 16-bit protected mode with SWITCHPM, one can transfer
- execution to a 32-bit segment with a far call.
- An example using the techniques discussed above is the MOVMEM function in
- the file EASYX.ASM. This function is not an interrupt handler; however, it is
- designed to be called from such handlers and must therefore abide by the same
- principles.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 54
-
-
-
-
-
-
- Appendix H: Debugging
-
-
- Unfortunately, neither Microsoft's CodeView nor Borland's Turbo Debugger
- are fully capable of debugging DOS-extended programs. The real-mode areas of
- such programs can be debugged with these debuggers provided that no attempts
- are made to step into calls to protected-mode subroutines. These subroutines
- must be debugged using other methods. This appendix presents useful
- information that should aid the programmer toward this end.
- Debugging protected-mode code without the aid of a software debugger will
- not prove as limiting as it may sound. In some cases there are better
- alternatives to software debuggers. For example, many programmers waste time
- stepping through code with a debugger trying to resolve a processor exception
- condition when a quick resolution to the problem could be gained with a deeper
- understanding of the processor and the exception.
-
-
- Resolving Bugs Affecting Program Output
-
-
- Bugs which lead to erroneous program output can typically be diagnosed
- with strategically located print statements. The XLIB archive contains a file
- call PMIO.INC which contains many protected-mode input/output routines,
- including a variety of print routines. The print routines never call BIOS or
- DOS (they use direct screen writes); consequently, they will work fine both in
- interrupt handlers and the main thread of execution.
- A similar method for locating bugs involves strategic location of the INT
- 3 instruction. This instruction will generate a breakpoint exception. The
- exception handlers in XLIBE will then give a complete report on register
- status as of the INT 3. The programmer will then be given the option to
- resume execution.
-
-
- Resolving Bugs Causing Processor Exceptions
-
-
- Bugs causing processor exceptions will commonly occur in protected mode.
- These bugs can be particularly annoying because they often hang or reboot the
- machine or leave it in an unstable state. However, the exception handlers in
- XLIBE should be able to successfully trap such bugs and then terminate the
- program in an orderly fashion.
- If the exception handlers in XLIBE fail to trap an exception, then it is
- likely the case that the bug is corrupting data or code used by the handlers.
- In any event, other methods may be used to track the bug.
- Once protected mode has been entered by calling either CALLPM or ENTERPM,
- one may return to the real-mode caller from any point in the code with a jump
- to either RETPM or EXITPM. Therefore, if an unidentified instruction is
- generating exceptions in protected mode, one may locate the instruction by
- placing jumps to RETPM or ENTERPM at various locations in the code. Initially
- the jumps should be placed early in the code and then moved forward. This way
- the processor exception is avoided as it is searched, thereby saving the time
- necessary to reboot after the exception occurs.
-
-
-
-
-
- 55
-
-
-
-
-
-
- XLIB is also designed such that INT 21H, function 4CH should terminate a
- program from either real or protected mode. This provides an alternative way
- to exit the program before execution of a faulty instruction.
- Processor exceptions are not generally difficult to resolve if the
- programmer has a thorough understanding of the exception. When an exception
- occurs, the exception handlers in XLIBE will print a report of register state
- to the screen. The exception usually can be resolved by examining this
- report. In particular, the report will contain the CS:EIP at which the
- exception occurred. Using this information, the programmer can typically
- identify the problematic instruction by examining a list file generated by the
- assembler or compiler.
-
-
- Processor Exceptions and Their Causes
-
-
- Many processor exceptions issue error codes. The exception handlers in
- XLIBE will always display such codes. For all exceptions except page faults
- (exception #14), the error code will be nonzero if the processor can associate
- the exception with a particular segment, in which event, the error code
- identifies the segment. In particular, bits 3-15 of the error code will be
- the selector for the segment. Bit 1 will be set if this selector refers to a
- gate descriptor in the interrupt descriptor table. If this bit is clear, then
- bit 2 identifies the selector as belonging to the global descriptor table (the
- bit is clear) or the local descriptor table (the bit is set). Bit 0 is set if
- an event external to the program generated the exception. Error codes are
- generated for exceptions: 8,10,11,12,13,14,15, and 17.
- The following is a summary of nearly all CPU exceptions:
-
- Exception #0, Divide Error - This exception occurs when a DIV or IDIV has been
- executed with a zero divisor, or when a quotient is too large to be contained
- in the targeted register (AL, AX, or EAX).
-
- Exception #1, Debug Exception - This exception occurs when a data breakpoint
- has been addressed, or upon execution of any instruction when single-step
- trapping has been enabled by setting the trap flag in the EFLAGS register. If
- the exception is due to a data breakpoint, then the debug status register
- (DR6) identifies the breakpoint. The lowest four bits of this register
- correspond to the four CPU breakpoint registers (DR0-DR3). Set bits indicate
- that the corresponding breakpoint condition is satisfied. Bit 14 of DR6 will
- be set if the exception is due to a single-step trap. XLIB does not implement
- single-step trapping.
-
- Exception #3, Breakpoint - This exception is generated by INT 3.
-
- Exception #4, Overflow - This exception occurs when the INTO instruction is
- executed with the overflow flag being set.
-
- Exception #5, Bounds Check - This exception occurs when a BOUND instruction is
- executed with the operand violating the specified limits.
-
- Exception #6, Invalid Opcode - This exception occurs when an unrecognizable
- instruction is encountered in the code sequence. Provided that there are no
- bugs in the compiler, this exception is almost certainly indicative of a bad
-
-
-
- 56
-
-
-
-
-
-
- transfer (JMP, CALL, RET, or IRET) or of code corruption. However, the
- exception can also be generated by instructions which are not intended for the
- current CPU mode (e.g. LLDT in real mode).
-
- Exception #7, Device Not Available - This exception occurs when an ESC
- instruction is executed under FPU emulation, or when a WAIT or ESC instruction
- is executed with the task-switch flag set in CR0. Neither case is likely
- under XLIB.
-
- Exception #8, Double Fault - If an exception occurs while the processor is
- attempting to call an exception handler for a prior exception, and if the two
- exceptions cannot be serialized, then a double fault exception is generated.
- The error code for this exception is always zero. Under XLIB, double faults
- are generally indicative of corruption of XLIB data used by the exception
- handlers.
-
- Exception #10, Invalid Task-State Segment - This exception occurs when an
- attempt is made to perform a task switch to a task having an invalid task-
- state segment. Since XLIB performs task switches only when servicing
- exceptions themselves, this condition generally derives from code corruption
- or an invalid transfer.
-
- Exception #11, Segment Not Present - This exception occurs when an attempt is
- made to load a segment register with a descriptor which is marked not-present.
- A segment might be so marked if its contents have been swapped to disk. Since
- all of the descriptors in XLIB are marked present, this exception likely
- derives from either corruption of the descriptor tables or an attempt to load
- a selector for an uninitialized descriptor.
-
- Exception #12, Stack Exception - Most stack exceptions are caused by limit
- violations in ESP or EBP. For example, if the value in ESP is beyond the
- stack segment limit then a PUSH or POP will generate a stack exception. It is
- also possible to have an "expand-down" stack where the segment limit is
- interpreted as a lower bound. In such cases a stack exception could be
- generated if a value in ESP or EBP were too small. Stack exceptions can also
- occur when SS is loaded with a selector for a descriptor which is marked not-
- present.
- Stack exceptions are generally common; however, they should be uncommon
- for XLIB programs while in protected mode. This follows because XLIB uses an
- expand-up stack with a FFFFFFFFH limit. Unless a switch has been made from
- the default stack, a stack exception under XLIB would typically be indicative
- of an invalid value being loaded to SS.
-
- Exception #13, General Protection Violation - This notorious exception is a
- catchall category on Intel processors that may be generated by a number of
- conditions. However, three conditions account for nearly all such exceptions
- in practice. These are: 1) An invalid value was loaded to a segment
- register, 2) An attempt was made to write to a code segment, or 3) Privilege
- rules were violated.
- Novices to protected mode often forget that segment registers must
- contain selectors in this mode. Invalid values are also frequently popped
- from the stack into segment registers because the stack has been corrupted or
- because the stack pointer has not been properly maintained.
-
-
-
-
- 57
-
-
-
-
-
-
- It must be remembered that writes to code segments are illegal in
- protected mode. That is, one cannot write to a code segment through the CS
- register. If code modification is desired, then load a data segment register
- with a selector to a descriptor which maps the code segment. The CSEGDSEL and
- TSEGDSEL selectors are included in XLIB for this purpose.
- Protected-mode programs can run at four different privilege levels. The
- highest is level zero and the lowest is level three. XLIB programs will
- either be operating at the highest or lowest level. Real-mode code always
- operates at level zero. If a memory manager other than HIMEM.SYS is
- installed, then the machine is likely using virtual 8086 mode in lieu of real
- mode. This is also the case under Windows and OS/2. Virtual 8086 mode is a
- subset of protected mode wherein real mode is simulated. Virtual 8086 mode
- always operates at level three.
- XLIB programs operating under DPMI will nearly always be at level three.
- Under VCPI the privilege level will depend upon the CPU mode. In protected
- mode the privilege level is zero, but in virtual 8086 mode the privilege level
- is three. If neither DPMI nor VCPI are present, then XLIB programs will
- operate at level zero regardless of CPU mode.
- A program operating at level three is always under the supervision of
- another program at level zero. The supervisor program will typically be a
- memory manager, Windows, or OS/2. When the level three program attempts to
- execute a privileged instruction, the supervisor program is informed of the
- attempt by the processor. The supervisor program may then execute the
- instruction in behalf of the unprivileged program, or it may terminate the
- unprivileged program with a privileged operation violation.
- Privileged instructions include reads and writes to IO ports and
- alterations to the interrupt flag. Both of these types of instructions are
- generally permitted by the supervisor program. However, other instructions (
- e.g. LGDT) will be denied.
- XLIB programmers have little occasion to use inadmissible privileged
- instructions. Therefore privileged operation exceptions are nearly always
- indicative of code corruption or of an invalid transfer.
-
- Exception #14, Page Fault - A principal protection mechanism of the processor
- is its memory paging mode. In this mode, memory is divided into 4K pages with
- the divisions being at 4K boundaries. A memory manager can mark certain pages
- as being absent, read-only, or privileged. An attempt to access an absent
- page or to write a read-only page always generates a page fault. A privileged
- page can be accessed only by code operating at privilege levels higher than
- three; hence, a page fault will occur if code at level three attempts to
- access such pages.
- When a page fault occurs, an error code is supplied by the processor to
- describe the fault. The error code is defined only in the lowest three bits.
- The zero bit describes whether the exception was caused by access of a not-
- present page (the bit is clear) or by a protection violation (the bit is set).
- Protection violations occur with attempts to access privileged pages or
- attempts to write read-only pages. Bit two of the error code describes the
- privilege mode at which the exception occurred. If the bit is clear, then the
- processor was executing in privileged mode. In this case, protection
- violations are generated only by attempts to write read-only pages. Bit one
- describes whether the fault took place during a read (the bit is clear) or a
- write (the bit is set).
- A page fault nearly always occurs because of an attempt to access a bad
- address or an attempt to transfer control to a bad address. Memory managers
-
-
-
- 58
-
-
-
-
-
-
- may mark unallocated pages as being not-present so that page faults will be
- generated whenever an attempt is made to access them. This way the programmer
- will be alerted to bad address computations. When VCPI is being used, XLIB
- becomes largely responsible for management of memory pages. XLIB will in fact
- mark all unallocated pages as not present. XLIB will mark all allocated pages
- as unprivileged and writable.
- The CR2 register will contain the address for the attempted access which
- generated the page fault. CR2 is displayed by the exception handlers in
- XLIBE.
-
- Exception #13 and Exception #14 are by far the most common exceptions
- occurring under XLIB programming. The following list of questions should be
- considered when attempting to resolve such exceptions. These questions are
- also relevant to other exceptions:
-
- 1) Did you improperly maintain the stack pointer?
- 2) Did you forget that only selectors can be loaded to segment registers in
- protected mode?
- 3) Did you compute an address incorrectly?
- 4) Did you attempt to write to a code segment using CS override?
- 5) Did you fail to terminate a subroutine with RET?
- 6) Did you forget to properly match CALL (far or near) and RET (e.g. Did you
- forget that TSEG procedures must be near)?
- 7) Did you attempt to execute a privileged instruction?
- 8) Did you fail to terminate an interrupt handler with IRET?
- 9) Did you terminate a protected-mode interrupt handler with IRET instead of
- IRETD?
- 10) If you are a TASM programmer, did you fail to specify LARGESTACK in your
- TSEG code?
-
-
- Miscellaneous Debugging Tips
-
-
- If a program runs unpredictably even when executed under identical
- circumstances, then the problem is due to an asynchronous phenomenon. This
- almost definitely implies a problem with a hardware interrupt handler. Such
- problems are oftentimes associated with the timer tick interrupt. This theory
- can sometimes be tested by disabling certain hardware interrupts with the
- interrupt mask register. The interrupt mask register for IRQs 0 through 7 is
- at port 21H. The masks for IRQs 8 through 15 are at port A1H. Set bits
- disable the corresponding IRQ. For example, the following code sequence would
- disable the timer tick interrupt (IRQ 0):
-
- IN AL,21H
- OR AL,01H
- OUT 21H,AL
-
- If a program leaves the machine in an unstable state, then it is possible
- that XLIB is not being terminated correctly. Try running an unregistered copy
- of XLIB and see if the registration reminder message is printed to the screen
- at program termination. If not, then the XLIB termination handler is likely
- not receiving control. This is likely due to code corruption.
-
-
-
-
- 59
-
-
-
-
-
-
- Most subroutines intended for protected-mode will also operate in real
- mode when applied to small problems. If a software debugger is deemed
- necessary, one might develop code in real mode and then convert to protected
- mode after debugging. 32-bit registers are admissible in real mode provided
- that no such register is used as a base or index register while containing a
- value greater than FFFFH.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 60