Jump to content

EXtended Memory Specification v2.0: Difference between revisions

From EDM2
Ak120 (talk | contribs)
mNo edit summary
 
(9 intermediate revisions by one other user not shown)
Line 1: Line 1:
===EDM/2 preamble===
This is the ''eXtended Memory Specification (XMS) v2.0'' as last published by [[Microsoft]] et al in 1988. It is republished here with inherent permission from the original publishers but you should keep in mind that it is an intellectual property of  Microsoft and other committee members and cannot be changed or reused without their permission and is not governed by the [[Attribution-Share Alike 3.0]] licence like the rest of the EDM/2 Wiki.


The content of the documentation is unchanged apart from the following:
* Sales, technical help, download and contact information has been removed as none of those services are available anymore.
* Miniscule changes have been made to the text, spelling errors, formatting errors and possible copy and paste errors have been fixed and/or noted.
Outside of formatting changes, adding Wikilinks and graphic improvements, the document shall be left as it is. While this version of the specification has some applicability to OS/2 v1.x, the OS/2 2.x and later versions reference the updated [[eXtended Memory Specification v3.0]], and this copy is here primarily since some other documents explicitly reference this version.
=eXtended Memory Specification (XMS), ver 2.0=
=eXtended Memory Specification (XMS), ver 2.0=
July 19, 1988
July 19, 1988
Line 29: Line 36:
====Helpful Diagram:====
====Helpful Diagram:====
<pre>
<pre>
    |                                                       |   Top of Memory
|                                             | Top of Memory
    |                                                       |
|                 /\                         |
    |                                                      |
|                 /||\                         |
    |                        /\                             |
|                 ||                         |
    |                       /||\                           |
|..............................................|
    |                       ||                             |
|       Possible Extended Memory Block         |
    |                        ||                            |
|..............................................|
    |.......................................................|
|                 ||                         |
    |                                                       |
|                 \||/                         |
    |                                                      |
|                 \/                         |
    |            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 EMBs could exist above 1088K (1MB+64K)   |
|                 ||                         |
    |                                                      |
|                 \||/                         |
    |                                                      |
|                 \/                         |
    |-------------------------------------------------------|   1088K
| Other UMBs could exist between 640K and 1MB |
    |                                                      |
|----------------------------------------------| 640K
    |                                                       |
|                                             |
    |                The High Memory Area                   |
|                                             |
    |                                                       |
|                                             |
    |                                                      |
|       Conventional or DOS Memory             |
    |=======================================================|   1024K or 1MB
|                                             |
    |                                                       |
|                                             |
    |                        /\                             |
|                                             |
    |                       /||\                           |
+----------------------------------------------+ 0K
    |                        ||                            |
    |                       ||                             |
    |.......................................................|
    |                                                       |
    |            Possible Upper Memory Block               |
    |.......................................................|
    |                       ||                             |
    |                        ||                             |
    |                      \||/                           |
    |                       \/                             |
    |                                                       |
    |        Other UMBs could exist between 640K and 1MB   |
    |                                                       |
    |-------------------------------------------------------|   640K
    |                                                       |
    |                                                       |
    |                                                       |
    |             Conventional or DOS Memory               |
    |                                                      |
    |                                                      |
    |                                                       |
    |                                                       |
    |                                                       |
    +-------------------------------------------------------+   0K
</pre>
</pre>
===DRIVER INSTALLATION===
===DRIVER INSTALLATION===
Line 115: Line 98:


Example:
Example:
            ; Get the address of the driver's control function
<code>
            mov    ax,4310h
; Get the address of the driver's control function
            int    2Fh
mov    ax,4310h
            mov    word ptr [XMSControl],bx        ; XMSControl is a DWORD
int    2Fh
            mov    word ptr [XMSControl+2],es
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
; Get the XMS driver's version number
            call    [XMSControl]    ; Get XMS Version Number
mov    ah,00h
 
call    [XMSControl]    ; Get XMS Version Number
</code>
;NOTE:Programs should make sure that at least 256 bytes of stack space is available before calling XMS API functions.
;NOTE:Programs should make sure that at least 256 bytes of stack space is available before calling XMS API functions.


Line 152: Line 136:


====Get XMS Version Number (Function 00h):====
====Get XMS Version Number (Function 00h):====
    ARGS:  AH = 00h
ARGS:  AH = 00h
    RETS:  AX = XMS version number
RETS:  AX = XMS version number
            BX = Driver internal revision number
        BX = Driver internal revision number
            DX = 0001h if the HMA exists, 0000h otherwise
        DX = 0001h if the HMA exists, 0000h otherwise
    ERRS:  None
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.
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.
Line 162: Line 146:


====Request High Memory Area (Function 01h):====
====Request High Memory Area (Function 01h):====
    ARGS:  AH = 01h
<pre>
            If the caller is a TSR or device driver,
ARGS:  AH = 01h
                DX = Space needed in the HMA by the caller in bytes
        If the caller is a TSR or device driver,
            If the caller is an application program,
            DX = Space needed in the HMA by the caller in bytes
                DX = FFFFh     
        If the caller is an application program,
    RETS:  AX = 0001h if the HMA is assigned to the caller, 0000h otherwise
            DX = FFFFh     
    ERRS:  BL = 80h if the function is not implemented
RETS:  AX = 0001h if the HMA is assigned to the caller, 0000h otherwise
    BL = 81h if a VDISK device is detected
ERRS:  BL = 80h if the function is not implemented
    BL = 90h if the HMA does not exist
BL = 81h if a VDISK device is detected
    BL = 91h if the HMA is already in use
BL = 90h if the HMA does not exist
    BL = 92h if DX is less than the /HMAMIN= parameter
BL = 91h if the HMA is already in use
 
BL = 92h if DX is less than the /HMAMIN= parameter
</pre>
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.
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.
;NOTE:See the sections "[[#Prioritizing HMA Usage]]" and "[[#High Memory Area Restrictions]]" below for more information.


====Release High Memory Area (Function 02h)====
====Release High Memory Area (Function 02h)====
    ARGS:  AH = 02h
<pre>
    RETS:  AX = 0001h if the HMA is successfully released, 0000h otherwise
ARGS:  AH = 02h
    ERRS:  BL = 80h if the function is not implemented
RETS:  AX = 0001h if the HMA is successfully released, 0000h otherwise
    BL = 81h if a VDISK device is detected
ERRS:  BL = 80h if the function is not implemented
    BL = 90h if the HMA does not exist
BL = 81h if a VDISK device is detected
    BL = 93h if the HMA was not allocated
BL = 90h if the HMA does not exist
 
BL = 93h if the HMA was not allocated
</pre>
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.
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)====
====Global Enable A20 (Function 03h)====
    ARGS:  AH = 03h
<pre>
    RETS:  AX = 0001h if the A20 line is enabled, 0000h otherwise
ARGS:  AH = 03h
    ERRS:  BL = 80h if the function is not implemented
RETS:  AX = 0001h if the A20 line is enabled, 0000h otherwise
    BL = 81h if a VDISK device is detected
ERRS:  BL = 80h if the function is not implemented
    BL = 82h if an A20 error occurs
BL = 81h if a VDISK device is detected
 
BL = 82h if an A20 error occurs
</pre>
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.
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.
;NOTE:On many machines, toggling the A20 line is a relatively slow operation.


====Global Disable A20 (Function 04h)====
====Global Disable A20 (Function 04h)====
    ARGS:  AH = 04h
<pre>
    RETS:  AX = 0001h if the A20 line is disabled, 0000h otherwise
ARGS:  AH = 04h
    ERRS:  BL = 80h if the function is not implemented
RETS:  AX = 0001h if the A20 line is disabled, 0000h otherwise
    BL = 81h if a VDISK device is detected
ERRS:  BL = 80h if the function is not implemented
    BL = 82h if an A20 error occurs
BL = 81h if a VDISK device is detected
    BL = 94h if the A20 line is still enabled
BL = 82h if an A20 error occurs
 
BL = 94h if the A20 line is still enabled
</pre>
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.
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.
;NOTE:On many machines, toggling the A20 line is a relatively slow operation.


====Local Enable A20 (Function 05h)====
====Local Enable A20 (Function 05h)====
    ARGS:  AH = 05h
<pre>
    RETS:  AX = 0001h if the A20 line is enabled, 0000h otherwise
ARGS:  AH = 05h
    ERRS:  BL = 80h if the function is not implemented
RETS:  AX = 0001h if the A20 line is enabled, 0000h otherwise
    BL = 81h if a VDISK device is detected
ERRS:  BL = 80h if the function is not implemented
    BL = 82h if an A20 error occurs
BL = 81h if a VDISK device is detected
 
BL = 82h if an A20 error occurs
</pre>
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.
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.
;NOTE:On many machines, toggling the A20 line is a relatively slow operation.


====Local Disable A20 (Function 06h)====
====Local Disable A20 (Function 06h)====
<pre>
     ARGS:  AH = 06h
     ARGS:  AH = 06h
     RETS:  AX = 0001h if the function succeeds, 0000h otherwise
     RETS:  AX = 0001h if the function succeeds, 0000h otherwise
Line 225: Line 215:
    BL = 82h if an A20 error occurs
    BL = 82h if an A20 error occurs
    BL = 94h if the A20 line is still enabled
    BL = 94h if the A20 line is still enabled
 
</pre>
This function cancels a previous call to Function 05h (Local Enable A20). It should only be used by programs which need direct access to extended memory.  Previous calls to Function 05h must be canceled before releasing control of the system.
This function cancels a previous call to Function 05h (Local Enable A20). It should only be used by programs which need direct access to extended 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.
;NOTE:On many machines, toggling the A20 line is a relatively slow operation.


====Query A20 (Function 07h)====
====Query A20 (Function 07h)====
<pre>
     ARGS:  AH = 07h
     ARGS:  AH = 07h
     RETS:  AX = 0001h if the A20 line is physically enabled, 0000h otherwise
     RETS:  AX = 0001h if the A20 line is physically enabled, 0000h otherwise
Line 235: Line 226:
    BL = 80h if the function is not implemented
    BL = 80h if the function is not implemented
    BL = 81h if a VDISK device is detected
    BL = 81h if a VDISK device is detected
 
</pre>
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.
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)====
====Query Free Extended Memory (Function 08h)====
<pre>
     ARGS:  AH = 08h
     ARGS:  AH = 08h
     RETS:  AX = Size of the largest free extended memory block in K-bytes
     RETS:  AX = Size of the largest free extended memory block in K-bytes
Line 245: Line 237:
    BL = 81h if a VDISK device is detected
    BL = 81h if a VDISK device is detected
    BL = A0h if all extended memory is allocated
    BL = A0h if all extended memory is allocated
 
</pre>
This function returns the size of the largest available extended memory block in the system.
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.
;NOTE:The 64K HMA is not included in the returned value even if it is not in use.


====Allocate Extended Memory Block (Function 09h)====
====Allocate Extended Memory Block (Function 09h)====
<pre>
     ARGS:  AH = 09h
     ARGS:  AH = 09h
             DX = Amount of extended memory being requested in K-bytes
             DX = Amount of extended memory being requested in K-bytes
Line 258: Line 251:
    BL = A0h if all available extended memory is allocated
    BL = A0h if all available extended memory is allocated
    BL = A1h if all available extended memory handles are in use
    BL = A1h if all available extended memory handles are in use
 
</pre>
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.
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.
;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)====
====Free Extended Memory Block (Function 0Ah)====
<pre>
     ARGS:  AH = 0Ah
     ARGS:  AH = 0Ah
             DX = Handle to the allocated block which should be freed
             DX = Handle to the allocated block which should be freed
Line 270: Line 264:
    BL = A2h if the handle is invalid
    BL = A2h if the handle is invalid
    BL = ABh if the handle is locked
    BL = ABh if the handle is locked
 
</pre>
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 before exiting. When an extended memory buffer is freed, its handle and all data stored in it become invalid and should not be accessed.
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 before exiting. 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)====
====Move Extended Memory Block (Function 0Bh)====
    ARGS:   AH = 0Bh
<code>
            DS:SI = Pointer to an Extended Memory Move Structure (see below)
:{|
    RETS:   AX = 0001h if the move is successful, 0000h otherwise
|ARGS:||AH = 0Bh
    ERRS:   BL = 80h if the function is not implemented
|-
    BL = 81h if a VDISK device is detected
|||DS:SI = Pointer to an Extended Memory Move Structure (see below)
    BL = 82h if an A20 error occurs
|-
    BL = A3h if the SourceHandle is invalid
|RETS:||AX = 0001h if the move is successful, 0000h otherwise
    BL = A4h if the SourceOffset is invalid
|-
    BL = A5h if the DestHandle is invalid
|ERRS:||BL = 80h if the function is not implemented
    BL = A6h if the DestOffset is invalid
|-
    BL = A7h if the Length is invalid
|||BL = 81h if a VDISK device is detected
    BL = A8h if the move has an invalid overlap
|-
    BL = A9h if a parity error occurs
|||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
|}
</code>
Extended Memory Move Structure Definition:
Extended Memory Move Structure Definition:


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


Lock Extended Memory Block (Function 0Ch):
====Lock Extended Memory Block (Function 0Ch)====
------------------------------------------
<pre>
 
     ARGS:  AH = 0Ch
     ARGS:  AH = 0Ch
             DX = Extended memory block handle to lock
             DX = Extended memory block handle to lock
Line 318: Line 326:
    BL = ACh if the block's lock count overflows
    BL = ACh if the block's lock count overflows
    BL = ADh if the lock fails
    BL = ADh if the lock fails
           
</pre>
    This function locks an extended memory block and returns its base  
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.
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.
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.


    NOTE: A block does not have to be locked before using Function 0Bh (Move
====Unlock Extended Memory Block (Function 0Dh)====
          Extended Memory Block).
<pre>
         
  "Lock counts" are maintained for EMBs.
 
 
Unlock Extended Memory Block (Function 0Dh):
--------------------------------------------
 
     ARGS:  AH = 0Dh
     ARGS:  AH = 0Dh
             DX = Extended memory block handle to unlock
             DX = Extended memory block handle to unlock
Line 340: Line 341:
    BL = A2h if the handle is invalid
    BL = A2h if the handle is invalid
    BL = AAh if the block is not locked
    BL = AAh if the block is not locked
   
</pre>
    This function unlocks a locked extended memory block. Any 32-bit
This function unlocks a locked extended memory block. Any 32-bit pointers into the block become invalid and should no longer be used.
pointers into the block become invalid and should no longer be used.
 
 
Get EMB Handle Information (Function 0Eh):
------------------------------------------


====Get EMB Handle Information (Function 0Eh)====
<pre>
     ARGS:  AH = 0Eh
     ARGS:  AH = 0Eh
    DX = Extended memory block handle
    DX = Extended memory block handle
Line 357: Line 355:
    BL = 81h if a VDISK device is detected
    BL = 81h if a VDISK device is detected
    BL = A2h if the handle is invalid
    BL = A2h if the handle is invalid
</pre>
This function returns additional information about an extended memory block to the caller.
;NOTE:To get the block's base address, use Function 0Ch (Lock Extended Memory Block).


    This function returns additional information about an extended memory
====Reallocate Extended Memory Block (Function 0Fh)====
block to the caller.
<pre>
 
    NOTE: To get the block's base address, use Function 0Ch (Lock Extended
  Memory Block).
         
         
Reallocate Extended Memory Block (Function 0Fh):
------------------------------------------------
 
     ARGS:  AH = 0Fh
     ARGS:  AH = 0Fh
    BX = New size for the extended memory block in K-bytes
    BX = New size for the extended memory block in K-bytes
Line 378: Line 371:
    BL = A2h if the handle is invalid
    BL = A2h if the handle is invalid
    BL = ABh if the block is locked
    BL = ABh if the block is locked
</pre>
This function attempts to reallocate an unlocked extended memory block so that it becomes the newly specified size. If the new size is smaller than the old block's size, all data at the upper end of the old block is lost.


    This function attempts to reallocate an unlocked extended memory block
====Request Upper Memory Block (Function 10h)====
so that it becomes the newly specified size.  If the new size is smaller
<pre>
than the old block's size, all data at the upper end of the old block is
lost.
 
 
Request Upper Memory Block (Function 10h):
------------------------------------------
 
     ARGS:  AH = 10h
     ARGS:  AH = 10h
    DX = Size of requested memory block in paragraphs
    DX = Size of requested memory block in paragraphs
Line 399: Line 387:
    BL = B0h if a smaller UMB is available
    BL = B0h if a smaller UMB is available
    BL = B1h if no UMBs are available
    BL = B1h if no UMBs are available
</pre>
This function attempts to allocate an upper memory block to the caller. If the function fails, the size of the largest free UMB is returned in DX.
;NOTE:By definition UMBs are located below the 1MB address boundary. The A20 Line does not need to be enabled before accessing an allocated UMB.
:UMBs are paragraph aligned.
:To determine the size of the largest available UMB, attempt to allocate one with a size of FFFFh.
:UMBs are unaffected by EMS calls.


    This function attempts to allocate an upper memory block to the caller.
====Release Upper Memory Block (Function 11h)====
If the function fails, the size of the largest free UMB is returned in DX.
<pre>
 
    NOTE: By definition UMBs are located below the 1MB address boundary.
  The A20 Line does not need to be enabled before accessing an
  allocated UMB.
 
  UMBs are paragraph aligned.
 
  To determine the size of the largest available UMB, attempt to
  allocate one with a size of FFFFh.
 
  UMBs are unaffected by EMS calls.
 
 
Release Upper Memory Block (Function 11h):
------------------------------------------
 
     ARGS:  AH = 11h
     ARGS:  AH = 11h
    DX = Segment number of the upper memory block
    DX = Segment number of the upper memory block
Line 423: Line 401:
     ERRS:  BL = 80h if the function is not implemented
     ERRS:  BL = 80h if the function is not implemented
    BL = B2h if the UMB segment number is invalid
    BL = B2h if the UMB segment number is invalid
 
</pre>
    This function frees a previously allocated upper memory block. When an
This function frees a previously allocated upper memory block. When an UMB has been released, any code or data stored in it becomes invalid and
UMB has been released, any code or data stored in it becomes invalid and
should not be accessed.
should not be accessed.


==Prioritizing HMA Usage==
==Prioritizing HMA Usage==
Line 439: Line 415:
The second method for optimizing HMA usage is through the /HMAMIN= parameter on the XMS device driver line.  The number after the parameter is defined to be the minimum amount of HMA space (in K-bytes) used by any driver or TSR. For example, if "DEVICE=HIMEM.SYS /HMAMIN=48" is in a user's CONFIG.SYS file, only programs which request at least 48K would be allowed to allocate the HMA. This number can be adjusted either by installation programs or by the user himself. If this parameter is not specified, the default value of 0 is used causing the HMA to be allocated on a first come, first served basis.
The second method for optimizing HMA usage is through the /HMAMIN= parameter on the XMS device driver line.  The number after the parameter is defined to be the minimum amount of HMA space (in K-bytes) used by any driver or TSR. For example, if "DEVICE=HIMEM.SYS /HMAMIN=48" is in a user's CONFIG.SYS file, only programs which request at least 48K would be allowed to allocate the HMA. This number can be adjusted either by installation programs or by the user himself. If this parameter is not specified, the default value of 0 is used causing the HMA to be allocated on a first come, first served basis.


    Note that this problem does not impact application programs. If the HMA
Note that this problem does not impact application programs. If the HMA is available when an application program starts, the application is free to use as much or as little of the HMA as it wants. For this reason, applications should pass FFFFh in DX when calling Function 01h.
is available when an application program starts, the application is free to
use as much or as little of the HMA as it wants. For this reason,
applications should pass FFFFh in DX when calling Function 01h.
 


==High Memory Area Restrictions==
==High Memory Area Restrictions==
Line 452: Line 424:
*Interrupt vectors must not point into the HMA. This is a result of the previous restriction. Note that interrupt vectors can point into any allocated upper memory blocks however.
*Interrupt vectors must not point into the HMA. This is a result of the previous restriction. Note that interrupt vectors can point into any allocated upper memory blocks however.


ERROR CODE INDEX:
==Error code index==
-----------------
 
If AX=0000h when a function returns and the high bit of BL is set,
If AX=0000h when a function returns and the high bit of BL is set,
 
<code>
    BL=80h if the function is not implemented
:BL=80h if the function is not implemented
      81h if a VDISK device is detected
::81h if a VDISK device is detected
      82h if an A20 error occurs
::82h if an A20 error occurs
      8Eh if a general driver error occurs
::8Eh if a general driver error occurs
      8Fh if an unrecoverable driver error occurs
::8Fh if an unrecoverable driver error occurs
      90h if the HMA does not exist
::90h if the HMA does not exist
      91h if the HMA is already in use
::91h if the HMA is already in use
      92h if DX is less than the /HMAMIN= parameter
::92h if DX is less than the /HMAMIN= parameter
      93h if the HMA is not allocated
::93h if the HMA is not allocated
      94h if the A20 line is still enabled
::94h if the A20 line is still enabled
      A0h if all extended memory is allocated
::A0h if all extended memory is allocated
      A1h if all available extended memory handles are in use
::A1h if all available extended memory handles are in use
      A2h if the handle is invalid
::A2h if the handle is invalid
      A3h if the SourceHandle is invalid
::A3h if the SourceHandle is invalid
      A4h if the SourceOffset is invalid
::A4h if the SourceOffset is invalid
      A5h if the DestHandle is invalid
::A5h if the DestHandle is invalid
      A6h if the DestOffset is invalid
::A6h if the DestOffset is invalid
      A7h if the Length is invalid
::A7h if the Length is invalid
      A8h if the move has an invalid overlap
::A8h if the move has an invalid overlap
      A9h if a parity error occurs
::A9h if a parity error occurs
      AAh if the block is not locked
::AAh if the block is not locked
      ABh if the block is locked
::ABh if the block is locked
      ACh if the block's lock count overflows
::ACh if the block's lock count overflows
      ADh if the lock fails
::ADh if the lock fails
      B0h if a smaller UMB is available
::B0h if a smaller UMB is available
      B1h if no UMBs are available
::B1h if no UMBs are available
      B2h if the UMB segment number is invalid
::B2h if the UMB segment number is invalid
 
</code>
�IMPLEMENTATION NOTES FOR DOS XMS DRIVERS:
==Implementation notes for DOS XMS drivers==
-----------------------------------------
*A DOS XMS driver's control function must begin with code similar to the following:
 
<code>
A DOS XMS driver's control function must begin with code similar to the
:{|
    following:
|XMMControl||proc||far
 
|-
XMMControl proc   far
|||jmp||short XCControlEntry||; For "hookability"
 
|-
    jmp     short XCControlEntry   ; For "hookability"
|||nop||||; NOTE: The jump must be a short
    nop     ; NOTE: The jump must be a short
|-
    nop     ; jump to indicate the end of
|||nop||||; jump to indicate the end of
    nop     ; any hook chain. The nop's
|-
    ;  allow a far jump to be
|||nop||||; any hook chain. The nop's allow a far jump to be patched in.
    ;  patched in.
|}
</code>
XCControlEntry:
XCControlEntry:
*XMS drivers must preserve all registers except those containing returned values across any function call.
*XMS drivers are required to hook INT 15h and watch for calls to functions 87h (Block Move) and 88h (Extended Memory Available). The INT 15h Block Move function must be hooked so that the state of the A20 line is preserved across the call. The INT 15h Extended Memory Available function must be hooked to return 0h to protect the HMA.
*In order to maintain compatibility with existing device drivers, DOS XMS drivers must not hook INT 15h until the first non-Version Number call to the control function is made.
*XMS drivers are required to check for the presence of drivers which use the IBM VDISK allocation scheme. Note that it is not sufficient to check for VDISK users at installation time but at the time when the HMA is first allocated. If a VDISK user is detected, the HMA must not be allocated. Microsoft will publish a standard method for detecting drivers which use the VDISK allocation scheme.
*XMS drivers which have a fixed number of extended memory handles (most do) should implement a command line parameter for adjusting that number (suggested name "/NUMHANDLES=")
*XMS drivers should make sure that the major DOS version number is greater than or equal to 3 before installing themselves.
*UMBs cannot occupy memory addresses that can be banked by EMS 4.0. EMS 4.0 takes precedence over UMBs for physically addressable memory.
*All driver functions must be re-entrant. Care should be taken to not leave interrupts disabled for long periods of time.
*Allocation of a zero length extended memory buffer is allowed. Programs which hook XMS drivers may need to reserve a handle for private use via this method.  Programs which hook an XMS driver should pass all requests for zero length EMBs to the next driver in the chain.
*Drivers should control the A20 line via an "enable count." Local Enable only enables the A20 line if the count is zero.  It then increments the count. Local Disable only disables A20 if the count is one. It then decrements the count. Global Enable/Disable keeps a flag which indicates the state of A20. They use Local Enable/Disable to actually change the state.


==Implementation notes for HIMEM.SYS==
*HIMEM.SYS currently supports true AT-compatibles, 386 AT machines, IBM PS/2s, AT&T 6300 Plus systems and Hewlett Packard Vectras.
*If HIMEM finds that it cannot properly control the A20 line or if there is no extended memory available when HIMEM.SYS is invoked, the driver does not install itself.  HIMEM.SYS displays the message "High Memory Area Unavailable" when this situation occurs.
*If HIMEM finds that the A20 line is already enabled when it is invoked, it will NOT change the A20 line's state. The assumption is that whoever enabled it knew what they were doing.  HIMEM.SYS displays the message "A20 Line Permanently Enabled" when this situation occurs.
*HIMEM.SYS is incompatible with IBM's VDISK.SYS driver and other drivers which use the VDISK scheme for allocating extended memory. However, HIMEM does attempt to detect these drivers and will not allocate the HMA if one is found.
*HIMEM.SYS supports the optional "/HMAMIN=" parameter. The valid values are decimal numbers between 0 and 63.
*By default, HIMEM.SYS has 32 extended memory handles available for use. This number may be adjusted with the "/NUMHANDLES=" parameter. The maximum value for this parameter is 128 and the minimum is 0. Each handle currently requires 6 bytes of resident space.


-  XMS drivers must preserve all registers except those containing
[[Category:DOS]]
    returned values across any function call.
 
-  XMS drivers are required to hook INT 15h and watch for calls to
    functions 87h (Block Move) and 88h (Extended Memory Available).  The
    INT 15h Block Move function must be hooked so that the state of the A20
    line is preserved across the call. The INT 15h Extended Memory
    Available function must be hooked to return 0h to protect the HMA.
 
-  In order to maintain compatibility with existing device drivers, DOS XMS
    drivers must not hook INT 15h until the first non-Version Number call
    to the control function is made.
 
-  XMS drivers are required to check for the presence of drivers which
    use the IBM VDISK allocation scheme.  Note that it is not sufficient to
    check for VDISK users at installation time but at the time when the HMA
    is first allocated.  If a VDISK user is detected, the HMA must not be
    allocated. Microsoft will publish a standard method for detecting
    drivers which use the VDISK allocation scheme.
 
-  XMS drivers which have a fixed number of extended memory handles (most
    do) should implement a command line parameter for adjusting that number
    (suggested name "/NUMHANDLES=")
 
-  XMS drivers should make sure that the major DOS version number is
    greater than or equal to 3 before installing themselves.
 
-  UMBs cannot occupy memory addresses that can be banked by EMS 4.0.
    EMS 4.0 takes precedence over UMBs for physically addressable memory.
 
-  All driver functions must be re-entrant.  Care should be taken to not
    leave interrupts disabled for long periods of time.
 
-  Allocation of a zero length extended memory buffer is allowed.  Programs
    which hook XMS drivers may need to reserve a handle for private use via
    this method.  Programs which hook an XMS driver should pass all requests
    for zero length EMBs to the next driver in the chain.
 
-  Drivers should control the A20 line via an "enable count." Local En-
    able only enables the A20 line if the count is zero.  It then increments
    the count. Local Disable only disables A20 if the count is one.  It
    then decrements the count. Global Enable/Disable keeps a flag which
    indicates the state of A20.  They use Local Enable/Disable to actually
    change the state.
 
�IMPLEMENTATION NOTES FOR HIMEM.SYS:
-----------------------------------
 
-  HIMEM.SYS currently supports true AT-compatibles, 386 AT machines, IBM
    PS/2s, AT&T 6300 Plus systems and Hewlett Packard Vectras.
 
-  If HIMEM finds that it cannot properly control the A20 line or if there
    is no extended memory available when HIMEM.SYS is invoked, the driver
    does not install itself.  HIMEM.SYS displays the message "High Memory
    Area Unavailable" when this situation occurs.
 
-  If HIMEM finds that the A20 line is already enabled when it is invoked,
    it will NOT change the A20 line's state.  The assumption is that whoever
    enabled it knew what they were doing.  HIMEM.SYS displays the message "A20
    Line Permanently Enabled" when this situation occurs.
 
-  HIMEM.SYS is incompatible with IBM's VDISK.SYS driver and other drivers
    which use the VDISK scheme for allocating extended memory.  However,
    HIMEM does attempt to detect these drivers and will not allocate the
    HMA if one is found.
 
-  HIMEM.SYS supports the optional "/HMAMIN=" parameter.  The valid values
    are decimal numbers between 0 and 63.
 
-  By default, HIMEM.SYS has 32 extended memory handles available for use.
    This number may be adjusted with the "/NUMHANDLES=" parameter.  The
    maximum value for this parameter is 128 and the minimum is 0.  Each
    handle currently requires 6 bytes of resident space.

Latest revision as of 16:40, 6 October 2017

EDM/2 preamble

This is the eXtended Memory Specification (XMS) v2.0 as last published by Microsoft et al in 1988. It is republished here with inherent permission from the original publishers but you should keep in mind that it is an intellectual property of Microsoft and other committee members and cannot be changed or reused without their permission and is not governed by the Attribution-Share Alike 3.0 licence like the rest of the EDM/2 Wiki.

The content of the documentation is unchanged apart from the following:

  • Sales, technical help, download and contact information has been removed as none of those services are available anymore.
  • Miniscule changes have been made to the text, spelling errors, formatting errors and possible copy and paste errors have been fixed and/or noted.

Outside of formatting changes, adding Wikilinks and graphic improvements, the document shall be left as it is. While this version of the specification has some applicability to OS/2 v1.x, the OS/2 2.x and later versions reference the updated eXtended Memory Specification v3.0, and this copy is here primarily since some other documents explicitly reference this version.

eXtended Memory Specification (XMS), ver 2.0

July 19, 1988

Copyright (c) 1988, Microsoft Corporation, Lotus Development Corporation, Intel Corporation, and AST Research, Inc.

This specification was jointly developed by Microsoft Corporation, Lotus Development Corporation, Intel Corporation,and AST Research, Inc. Although it has been released into the public domain and is not confidential or proprietary, the specification is still the copyright and property of Microsoft Corporation, Lotus Development Corporation, Intel Corporation, and AST Research, Inc.

Disclaimer of Warranty

MICROSOFT CORPORATION, LOTUS DEVELOPMENT CORPORATION, INTEL CORPORATION, AND AST RESEARCH, INC., EXCLUDE ANY AND ALL IMPLIED WARRANTIES, INCLUDING WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. NEITHER MICROSOFT NOR LOTUS NOR INTEL NOR AST RESEARCH MAKE ANY WARRANTY OF REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS SPECIFICATION, ITS QUALITY, PERFORMANCE, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. NEITHER MICROSOFT NOR LOTUS NOR INTEL NOR AST RESEARCH SHALL HAVE ANY LIABILITY FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RESULTING FROM THE USE OR MODIFICATION OF THIS SPECIFICATION.

This specification uses the following trademarks:

Intel is a registered trademark of Intel Corporation, Microsoft is a registered trademark of Microsoft Corporation, Lotus is a registered trademark of Lotus Development Corporation, and AST is a registered trademark of AST Research, Inc.

Extended Memory Specification

The purpose of this document is to define the Extended Memory Specification (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 to extended 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 before exiting. 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.

Get EMB Handle Information (Function 0Eh)

    ARGS:   AH = 0Eh
	    DX = Extended memory block handle
    RETS:   AX = 0001h if the block's information is found, 0000h otherwise
	    BH = The block's lock count
	    BL = Number of free EMB handles in the system
	    DX = The block's length in K-bytes
    ERRS:   BL = 80h if the function is not implemented
	    BL = 81h if a VDISK device is detected
	    BL = A2h if the handle is invalid

This function returns additional information about an extended memory block to the caller.

NOTE
To get the block's base address, use Function 0Ch (Lock Extended Memory Block).

Reallocate Extended Memory Block (Function 0Fh)

    ARGS:   AH = 0Fh
	    BX = New size for the extended memory block in K-bytes
	    DX = Unlocked extended memory block handle to reallocate
    RETS:   AX = 0001h if the block is reallocated, 0000h otherwise
    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
	    BL = A2h if the handle is invalid
	    BL = ABh if the block is locked

This function attempts to reallocate an unlocked extended memory block so that it becomes the newly specified size. If the new size is smaller than the old block's size, all data at the upper end of the old block is lost.

Request Upper Memory Block (Function 10h)

    ARGS:   AH = 10h
	    DX = Size of requested memory block in paragraphs
    RETS:   AX = 0001h if the request is granted, 0000h otherwise
	    BX = Segment number of the upper memory block
            If the request is granted,
		DX = Actual size of the allocated block in paragraphs
	    otherwise,
		DX = Size of the largest available UMB in paragraphs
    ERRS:   BL = 80h if the function is not implemented
	    BL = B0h if a smaller UMB is available
	    BL = B1h if no UMBs are available

This function attempts to allocate an upper memory block to the caller. If the function fails, the size of the largest free UMB is returned in DX.

NOTE
By definition UMBs are located below the 1MB address boundary. The A20 Line does not need to be enabled before accessing an allocated UMB.
UMBs are paragraph aligned.
To determine the size of the largest available UMB, attempt to allocate one with a size of FFFFh.
UMBs are unaffected by EMS calls.

Release Upper Memory Block (Function 11h)

    ARGS:   AH = 11h
	    DX = Segment number of the upper memory block
    RETS:   AX = 0001h if the block was released, 0000h otherwise
    ERRS:   BL = 80h if the function is not implemented
	    BL = B2h if the UMB segment number is invalid

This function frees a previously allocated upper memory block. When an UMB has been released, any code or data stored in it becomes invalid and should not be accessed.

Prioritizing HMA Usage

For DOS users to receive the maximum benefit from the High Memory Area, programs which use the HMA must store as much of their resident code in it as is possible. It is very important that developers realize that the HMA is allocated as a single unit.

For example, a TSR program which grabs the HMA and puts 10K of code into it may prevent a later TSR from putting 62K into the HMA. Obviously, regular DOS programs would have more memory available to them below the 640K line if the 62K TSR was moved into the HMA instead of the 10K one.

The first method for dealing with conflicts such as this is to require programs which use the HMA to provide a command line option for disabling this feature. It is crucial that TSRs which do not make full use of the HMA provide such a switch on their own command line (suggested name "/NOHMA").

The second method for optimizing HMA usage is through the /HMAMIN= parameter on the XMS device driver line. The number after the parameter is defined to be the minimum amount of HMA space (in K-bytes) used by any driver or TSR. For example, if "DEVICE=HIMEM.SYS /HMAMIN=48" is in a user's CONFIG.SYS file, only programs which request at least 48K would be allowed to allocate the HMA. This number can be adjusted either by installation programs or by the user himself. If this parameter is not specified, the default value of 0 is used causing the HMA to be allocated on a first come, first served basis.

Note that this problem does not impact application programs. If the HMA is available when an application program starts, the application is free to use as much or as little of the HMA as it wants. For this reason, applications should pass FFFFh in DX when calling Function 01h.

High Memory Area Restrictions

  • Far pointers to data located in the HMA cannot be passed to DOS. DOS normalizes any pointer which is passed into it. This will cause data addresses in the HMA to be invalidated.
  • Disk I/O directly into the HMA (via DOS, INT 13h, or otherwise) is not recommended.
  • Programs, especially drivers and TSRs, which use the HMA *MUST* use as much of it as possible. If a driver or TSR is unable to use at least 90% of the available HMA (typically ~58K), they must provide a command line switch for overriding HMA usage. This will allow the user to configure his machine for optimum use of the HMA.
  • Device drivers and TSRs cannot leave the A20 line permanently turned on. Several applications rely on 1MB memory wrap and will overwrite the HMA if the A20 line is left enabled potentially causing a system crash.
  • Interrupt vectors must not point into the HMA. This is a result of the previous restriction. Note that interrupt vectors can point into any allocated upper memory blocks however.

Error code index

If AX=0000h when a function returns and the high bit of BL is set,

BL=80h if the function is not implemented
81h if a VDISK device is detected
82h if an A20 error occurs
8Eh if a general driver error occurs
8Fh if an unrecoverable driver error occurs
90h if the HMA does not exist
91h if the HMA is already in use
92h if DX is less than the /HMAMIN= parameter
93h if the HMA is not allocated
94h if the A20 line is still enabled
A0h if all extended memory is allocated
A1h if all available extended memory handles are in use
A2h if the handle is invalid
A3h if the SourceHandle is invalid
A4h if the SourceOffset is invalid
A5h if the DestHandle is invalid
A6h if the DestOffset is invalid
A7h if the Length is invalid
A8h if the move has an invalid overlap
A9h if a parity error occurs
AAh if the block is not locked
ABh if the block is locked
ACh if the block's lock count overflows
ADh if the lock fails
B0h if a smaller UMB is available
B1h if no UMBs are available
B2h if the UMB segment number is invalid

Implementation notes for DOS XMS drivers

  • A DOS XMS driver's control function must begin with code similar to the following:

XMMControl proc far
jmp short XCControlEntry ; For "hookability"
nop ; NOTE: The jump must be a short
nop ; jump to indicate the end of
nop ; any hook chain. The nop's allow a far jump to be patched in.

XCControlEntry:

  • XMS drivers must preserve all registers except those containing returned values across any function call.
  • XMS drivers are required to hook INT 15h and watch for calls to functions 87h (Block Move) and 88h (Extended Memory Available). The INT 15h Block Move function must be hooked so that the state of the A20 line is preserved across the call. The INT 15h Extended Memory Available function must be hooked to return 0h to protect the HMA.
  • In order to maintain compatibility with existing device drivers, DOS XMS drivers must not hook INT 15h until the first non-Version Number call to the control function is made.
  • XMS drivers are required to check for the presence of drivers which use the IBM VDISK allocation scheme. Note that it is not sufficient to check for VDISK users at installation time but at the time when the HMA is first allocated. If a VDISK user is detected, the HMA must not be allocated. Microsoft will publish a standard method for detecting drivers which use the VDISK allocation scheme.
  • XMS drivers which have a fixed number of extended memory handles (most do) should implement a command line parameter for adjusting that number (suggested name "/NUMHANDLES=")
  • XMS drivers should make sure that the major DOS version number is greater than or equal to 3 before installing themselves.
  • UMBs cannot occupy memory addresses that can be banked by EMS 4.0. EMS 4.0 takes precedence over UMBs for physically addressable memory.
  • All driver functions must be re-entrant. Care should be taken to not leave interrupts disabled for long periods of time.
  • Allocation of a zero length extended memory buffer is allowed. Programs which hook XMS drivers may need to reserve a handle for private use via this method. Programs which hook an XMS driver should pass all requests for zero length EMBs to the next driver in the chain.
  • Drivers should control the A20 line via an "enable count." Local Enable only enables the A20 line if the count is zero. It then increments the count. Local Disable only disables A20 if the count is one. It then decrements the count. Global Enable/Disable keeps a flag which indicates the state of A20. They use Local Enable/Disable to actually change the state.

Implementation notes for HIMEM.SYS

  • HIMEM.SYS currently supports true AT-compatibles, 386 AT machines, IBM PS/2s, AT&T 6300 Plus systems and Hewlett Packard Vectras.
  • If HIMEM finds that it cannot properly control the A20 line or if there is no extended memory available when HIMEM.SYS is invoked, the driver does not install itself. HIMEM.SYS displays the message "High Memory Area Unavailable" when this situation occurs.
  • If HIMEM finds that the A20 line is already enabled when it is invoked, it will NOT change the A20 line's state. The assumption is that whoever enabled it knew what they were doing. HIMEM.SYS displays the message "A20 Line Permanently Enabled" when this situation occurs.
  • HIMEM.SYS is incompatible with IBM's VDISK.SYS driver and other drivers which use the VDISK scheme for allocating extended memory. However, HIMEM does attempt to detect these drivers and will not allocate the HMA if one is found.
  • HIMEM.SYS supports the optional "/HMAMIN=" parameter. The valid values are decimal numbers between 0 and 63.
  • By default, HIMEM.SYS has 32 extended memory handles available for use. This number may be adjusted with the "/NUMHANDLES=" parameter. The maximum value for this parameter is 128 and the minimum is 0. Each handle currently requires 6 bytes of resident space.