Extended Memory Specification
=============================

The purpose of this document is to define the Extended Memory
Specifi-
cation (XMS) version 2.00 for MS-DOS.  XMS allows DOS programs to
utilize
additional memory found in Intel's 80286 and 80386 based machines in
a consistent, machine independent manner.  With some restrictions,
XMS adds
almost 64K to the 640K which DOS programs can access
directly.Depending on
available hardware, XMS may provide even more memory to DOS programs. 
XMS
also provides DOS programs with a standard method of storing data in
extended
memory.

DEFINITIONS:
------------

Extended
Memory      -   Memory in 80286 and 80386 based machines which is
located
above the 1MB address boundary.

High Memory
Area (HMA)  -   The first 64K of extended memory.  The High Memory
Area is unique because code can be executed in it while
in real mode.  The HMA officially starts at FFFF:10h
and ends at FFFF:FFFFh making it 64K-16 bytes in length.

Upper Memory
Blocks (UMBs)-  Blocks of memory available on some 80x86 based
machines
which are located between DOS's 640K limit and the
1MB address boundary.  The number, size, and location
of these blocks vary widely depending upon the types
of hardware adapter cards installed in the machine.

Extended Memory
Blocks (EMBs)-  Blocks of extended memory located above the HMA
which                    can only be used for data storage.

A20 Line    -   The 21st address line of 80x86 CPUs.  Enabling the
A20
line allows access to the HMA.

XMM         -   An Extended Memory Manager.  A DOS device driver
which
implements XMS.  XMMs are machine specific but allow
programs to use extended memory in a machine-independent
manner.

HIMEM.SYS   -   The Extended Memory Manager currently being
distributed
by Microsoft.

Helpful Diagram:

|                                                       |   Top of
Memory
|                                                       |
|                                                       |
|                        /\                             |
|                       /||\                            |
|                        ||                             |
|                        ||                             |
|.......................................................|
|                                                       |
|                                                       |
|             Possible Extended Memory Block            |
|                                                       |
|                                                       |
|.......................................................|
|                        ||                             |
|                        ||                             |
|                       \||/                            |
|                        \/                             |
|                                                       |
|                                                       |
|       Other EMBs could exist above 1088K (1MB+64K)    |
|                                                       |
|                                                       |
|-------------------------------------------------------|   1088K
|                                                       |
|                                                       |
|                The High Memory Area                   |
|                                                       |
|                                                       |
|====================================================== 1024K or
1MB
|                                                       |
|                        /\                             |
|                       /||\                            |
|                        ||                             |
|                        ||                             |
|.......................................................|
|                                                       |
|             Possible Upper Memory Block               |
|.......................................................|
|                        ||                             |
|                        ||                             |
|                       \||/                            |
|                        \/                             |
|                                                       |
|        Other UMBs could exist between 640K and 1MB    |
|                                                       |
|-------------------------------------------------------|   640K
|                                                       |
|                                                       |
|                                                       |
|             Conventional or DOS Memory                |
|                                                       |
|                                                       |
|                                                       |
|                                                       |
|                                                       |
+-------------------------------------------------------+   0K
DRIVER INSTALLATION:
--------------------

An XMS driver is installed by including a DEVICE= statement in the
machine's CONFIG.SYS file.  It must be installed prior to any other
devices or TSRs which use it.  An optional parameter after the
driver's 
name (suggested name "/HMAMIN=") indicates the minimum amount of
space in
the HMA a program can use.  Programs which use less than the minimum
will
not be placed in the HMA.  See "Prioritizing HMA Usage" below for
more
information.  A second optional parameter (suggested name
"/NUMHANDLES=")
allows users to specify the maximum number of extended memory blocks
which
may be allocated at any time.

NOTE: XMS requires DOS 3.00 or above.


THE PROGRAMMING API:
--------------------

The XMS API Functions are accessed via the XMS driver's Control
Function.
The address of the Control Function is determined via INT 2Fh. 
First, a
program should determine if an XMS driver is installed.  Next, it
should
retrieve the address of the driver's Control Function.  It can then
use any
of the available XMS functions.  The functions are divided into
several
groups:

1. Driver Information Functions (0h)
2. HMA Management Functions (1h-2h)
3. A20 Management Functions (3h-7h)
4. Extended Memory Management Functions (8h-Fh)
5. Upper Memory Management Functions (10h-11h)


DETERMINING IF AN XMS DRIVER IS INSTALLED:
------------------------------------------

The recommended way of determining if an XMS driver is installed is
to
set AH=43h and AL=00h and then execute INT 2Fh.  If an XMS driver is
available,
80h will be returned in AL.

Example:
; Is an XMS driver installed?
mov     ax,4300h
int     2Fh         
cmp     al,80h  
jne     NoXMSDriver


CALLING THE API FUNCTIONS:
--------------------------

Programs can execute INT 2Fh with AH=43h and AL=10h to obtain the
address
of the driver's control function.  The address is returned in ES:BX.  
This
function is called to access all of the XMS functions.  It should be
called
with AH set to the number of the API function requested.  The API
function
will put a success code of 0001h or 0000h in AX.  If the function
succeeded
(AX=0001h), additional information may be passed back in BX and DX. 
If the
function failed (AX=0000h), an error code may be returned in BL. 
Valid
error codes have their high bit set.  Developers should keep in mind
that
some of the XMS API functions may not be implemented by all drivers
and will
return failure in all cases.

Example:
; Get the address of the driver's control function
mov     ax,4310h
int     2Fh
mov     word ptr [XMSControl],bx        ; XMSControl is a DWORD
mov     word ptr [XMSControl+2],es

; Get the XMS driver's version number
mov     ah,00h
call    [XMSControl]    ; Get XMS Version Number

NOTE: Programs should make sure that at least 256 bytes of stack
space
is available before calling XMS API functions.


API FUNCTION DESCRIPTIONS:
--------------------------

The following XMS API functions are available:

0h)  Get XMS Version Number
1h)  Request High Memory Area
2h)  Release High Memory Area
3h)  Global Enable A20
4h)  Global Disable A20
5h)  Local Enable A20
6h)  Local Disable A20
7h)  Query A20
8h)  Query Free Extended Memory
9h)  Allocate Extended Memory Block
Ah)  Free Extended Memory Block
Bh)  Move Extended Memory Block
Ch)  Lock Extended Memory Block
Dh)  Unlock Extended Memory Block
Eh)  Get Handle Information
Fh)  Reallocate Extended Memory Block
10h)  Request Upper Memory Block
11h)  Release Upper Memory Block

Each is described below.


Get XMS Version Number (Function 00h):
--------------------------------------

ARGS:   AH = 00h
RETS:   AX = XMS version number
BX = Driver internal revision number
DX = 0001h if the HMA exists, 0000h otherwise
ERRS:   None

This function returns with AX equal to a 16-bit BCD number
representing
the revision of the DOS Extended Memory Specification which the
driver
implements (e.g. AX=0235h would mean that the driver implemented XMS
version
2.35).BX is set equal to the driver's internal revision number mainly 
for
debugging purposes.  DX indicates the existence of the HMA (not its
availability) and is intended mainly for installation programs.

NOTE: This document defines version 2.00 of the specification.


Request High Memory Area (Function 01h):
----------------------------------------

ARGS:   AH = 01h
If the caller is a TSR or device driver,
DX = Space needed in the HMA by the caller in bytes
If the caller is an application program,
DX = FFFFh     
RETS:   AX = 0001h if the HMA is assigned to the caller, 0000h
otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = 90h if the HMA does not exist
BL = 91h if the HMA is already in use
BL = 92h if DX is less than the /HMAMIN= parameter

This function attempts to reserve the 64K-16 byte high memory area
for
the caller.  If the HMA is currently unused, the caller's size
parameter is
compared to the /HMAMIN= parameter on the driver's command line.  If
the
value passed by the caller is greater than or equal to the amount
specified
by the driver's parameter, the request succeeds.  This provides the
ability
to ensure that programs which use the HMA efficiently have priority
over
those which do not.

NOTE: See the sections "Prioritizing HMA Usage" and "High Memory
Area          Restrictions" below for more information.


Release High Memory Area (Function 02h):
----------------------------------------

ARGS:   AH = 02h
RETS:   AX = 0001h if the HMA is successfully released, 0000h
otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = 90h if the HMA does not exist
BL = 93h if the HMA was not allocated

This function releases the high memory area and allows other programs 
to
use it.  Programs which allocate the HMA must release it before
exiting.  
When the HMA has been released, any code or data stored in it becomes 
invalid
and should not be accessed.


Global Enable A20 (Function 03h):
---------------------------------

ARGS:   AH = 03h
RETS:   AX = 0001h if the A20 line is enabled, 0000h otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = 82h if an A20 error occurs

This function attempts to enable the A20 line.  It should only be
used
by programs which have control of the HMA.  The A20 line should be
turned
off via Function 04h (Global Disable A20) before a program releases
control
of the system.

NOTE: On many machines, toggling the A20 line is a relatively slow
operation.


Global Disable A20 (Function 04h):
----------------------------------

ARGS:   AH = 04h
RETS:   AX = 0001h if the A20 line is disabled, 0000h otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = 82h if an A20 error occurs
BL = 94h if the A20 line is still enabled

This function attempts to disable the A20 line.  It should only be
used
by programs which have control of the HMA.  The A20 line should be
disabled
before a program releases control of the system.

NOTE: On many machines, toggling the A20 line is a relatively slow
operation.


Local Enable A20 (Function 05h):
--------------------------------

ARGS:   AH = 05h
RETS:   AX = 0001h if the A20 line is enabled, 0000h otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = 82h if an A20 error occurs

This function attempts to enable the A20 line.  It should only be
used
by programs which need direct access to extended memory.  Programs
which use
this function should call Function 06h (Local Disable A20) before
releasing
control of the system.

NOTE: On many machines, toggling the A20 line is a relatively slow
operation.


Local Disable A20 (Function 06h):
---------------------------------

ARGS:   AH = 06h
RETS:   AX = 0001h if the function succeeds, 0000h otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = 82h if an A20 error occurs
BL = 94h if the A20 line is still enabled

This function cancels a previous call to Function 05h (Local Enable
A20).  It should only be used by programs which need direct access
toextended memory.  Previous calls to Function 05h must be canceled
before
releasing control of the system.

NOTE: On many machines, toggling the A20 line is a relatively slow
operation.


Query A20 (Function 07h):
-------------------------

ARGS:   AH = 07h
RETS:   AX = 0001h if the A20 line is physically enabled, 0000h
otherwise
ERRS:   BL = 00h if the function succeeds
BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected

This function checks to see if the A20 line is physically enabled. 
It
does this in a hardware independent manner by seeing if "memory wrap" 
occurs.


Query Free Extended Memory (Function 08h):
------------------------------------------

ARGS:   AH = 08h
RETS:   AX = Size of the largest free extended memory block in
K-bytes
DX = Total amount of free extended memory in K-bytes
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = A0h if all extended memory is allocated

This function returns the size of the largest available extended
memory
block in the system.

NOTE: The 64K HMA is not included in the returned value even if it
is  not in use.


Allocate Extended Memory Block (Function 09h):
----------------------------------------------

ARGS:   AH = 09h
DX = Amount of extended memory being requested in K-bytes
RETS:   AX = 0001h if the block is allocated, 0000h otherwise
DX = 16-bit handle to the allocated block
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = A0h if all available extended memory is allocated
BL = A1h if all available extended memory handles are in use

This function attempts to allocate a block of the given size out of
the
pool of free extended memory.  If a block is available, it is
reserved
for the caller and a 16-bit handle to that block is returned.  The
handle
should be used in all subsequent extended memory calls.  If no memory 
was
allocated, the returned handle is null.

NOTE: Extended memory handles are scarce resources.  Programs should
try to allocate as few as possible at any one time.  When all
of a driver's handles are in use, any free extended memory is
unavailable.


Free Extended Memory Block (Function 0Ah):
------------------------------------------

ARGS:   AH = 0Ah
DX = Handle to the allocated block which should be freed
RETS:   AX = 0001h if the block is successfully freed, 0000h
otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = A2h if the handle is invalid
BL = ABh if the handle is locked

This function frees a block of extended memory which was previously
allocated using Function 09h (Allocate Extended Memory Block). 
Programs
which allocate extended memory should free their memory blocks
beforeexiting.  When an extended memory buffer is freed, its handle
and all data
stored in it become invalid and should not be accessed.


Move Extended Memory Block (Function 0Bh):
------------------------------------------

ARGS:   AH = 0Bh
DS:SI = Pointer to an Extended Memory Move Structure (see below)
RETS:   AX = 0001h if the move is successful, 0000h otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = 82h if an A20 error occurs
BL = A3h if the SourceHandle is invalid
BL = A4h if the SourceOffset is invalid
BL = A5h if the DestHandle is invalid
BL = A6h if the DestOffset is invalid
BL = A7h if the Length is invalid
BL = A8h if the move has an invalid overlap
BL = A9h if a parity error occurs

Extended Memory Move Structure Definition:

ExtMemMoveStruct    struc
Length              dd  ?   ; 32-bit number of bytes to transfer
SourceHandle        dw  ?   ; Handle of source block
SourceOffset        dd  ?   ; 32-bit offset into source 
DestHandle          dw  ?   ; Handle of destination block
DestOffset          dd  ?   ; 32-bit offset into destination block
ExtMemMoveStruct    ends

This function attempts to transfer a block of data from one location
to
another.  It is primarily intended for moving blocks of data between
conventional memory and extended memory, however it can be used for
moving
blocks within conventional memory and within extended memory.

NOTE: If SourceHandle is set to 0000h, the SourceOffset is
interpreted
as a standard segment:offset pair which refers to memory that is
directly accessible by the processor.  The segment:offset pair
is stored in Intel DWORD notation.  The same is true for DestHandle
and DestOffset.

SourceHandle and DestHandle do not have to refer to locked memory
blocks.

Length must be even.Although not required, WORD-aligned moves
can be significantly faster on most machines.  DWORD aligned move
can be even faster on 80386 machines.

If the source and destination blocks overlap, only forward moves
(i.e. where the source base is less than the destination base) are
guaranteed to work properly.

Programs should not enable the A20 line before calling this
function.  The state of the A20 line is preserved.

This function is guaranteed to provide a reasonable number of
interrupt windows during long transfers.


Lock Extended Memory Block (Function 0Ch):
------------------------------------------

ARGS:   AH = 0Ch
DX = Extended memory block handle to lock
RETS:   AX = 0001h if the block is locked, 0000h otherwise
DX:BX = 32-bit linear address of the locked block
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = A2h if the handle is invalid
BL = ACh if the block's lock count overflows
BL = ADh if the lock fails

This function locks an extended memory block and returns its base 
address as a 32-bit linear address.  Locked memory blocks are
guaranteed not
to move.  The 32-bit pointer is only valid while the block is
locked.Locked blocks should be unlocked as soon as possible.

NOTE: A block does not have to be locked before using Function 0Bh
(Move
Extended Memory Block).

"Lock counts" are maintained for EMBs.


Unlock Extended Memory Block (Function 0Dh):
--------------------------------------------

ARGS:   AH = 0Dh
DX = Extended memory block handle to unlock
RETS:   AX = 0001h if the block is unlocked, 0000h otherwise
ERRS:   BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = A2h if the handle is invalid
BL = AAh if the block is not locked

This function unlocks a locked extended memory block.  Any 32-bit
pointers into the block become invalid and should no longer be used.