There is an introduction in the comments at the beginning of the unit.

Due to popular demand I am including a demonstration program which shows the
basics of using my XMS unit.  It demonstrates how to verify installation of
XMS, determine enough free XMS is available, allocating and deallocating an
XMS block, and moving information to and from said XMS block.

For those of you who may not know what XMS is, or who may be confused about
it, here is a brief description in my own words:

The original 8088/8086 (and NEC V20/V30 and 80188/80186) CPUs could only
address 1 megabyte of memory.  The 286 increased this to 16 MB, but only in
protected mode (except the HMA).  The 386 increased this to 4 GB, but also
only in protected mode (unless you perform certain tricks).  All memory
from 0K to 640K is CONVENTIONAL memory.  Any memory between 640K and 1 MB is
UPPER MEMORY or MAPPED EMS.  The first 64K less 16 bytes of memory above the
1 MB boundary is the HIGH MEMORY AREA, or HMA.  All memory above the 1 MB
boundary is EXTENDED memory.  EXPANDED memory does not have any physical
addresses associated with it.  It is mapped into conventional memory, usually
into a page frame located between 640K and 1MB.  Expanded memory used to be
physically seperate memory on a plug in card, but modern expanded memory
emulators such as EMM386 take extended memory and use the 386 paging
registers to emulate expanded memory.

Originally, the only way to access extended memory was through protected mode
or using the INT 15h interface.  Then Microsoft came up with the eXtended
Memory Specification, or XMS.  XMS calls for an eXtended Memory Manager, or
XMM.  HIMEM.SYS is such an XMM.  XMM's allocate all extended memory for
themselves, and then dish it out via the XMS interface.  All EXTENDED memory
accessed via an XMM is called XMS memory.  Therefore, all XMS memory is
extended memory, but not all extended memory is necessarily XMS memory.

Nowadays, the difference is pretty much academic.  All modern machines have
an XMM running and therefore all extended memory is XMS.  There are very few
programs out there which can work with extended memory directly.

This is good, in that you can pretty much be assured that any machine your
program is going to run on will support XMS.  The bad news is that XMS can
be very slow because you can't access it directly.  In order to use it, you
must COPY information to and from it.  Say you are writing a graphics editing
program.  You have two images in XMS, each occupying 300K.  To load the first
into your conventional memory buffer, you must copy that 300K into your
buffer.  If the user wants to switch screens, you must then recopy that 300K
back to XMS to save changes, then copy the other 300K into conventional every
time you want to switch pictures.

My own subjective tests reveal that copying from conventional memory to XMS
is always faster than the reverse by a significant amount.  Also, copying
from XMS to XMS is slightly faster then XMS to conventional.  This is
probably due to not having to convert linear to segment:offset addressing.
I have found that XMS is fastest when in real mode (i.e. no EMM installed),
and that the Win95 XMM is MUCH faster than the MS-DOS 6.22 XMM when also
running with EMS.  (Vanilla DOS XMS is always fastest.)

XMS is best used for storing static data, i.e. data that doesn't get changed
and therefore does not need to be recopied back into XMS to save changes.

For storing dynamic data that is too large to fit into conventional memory,
EMS is the best option.  Unfortunately, EMS is not installed on a large
percentage of machines, even though they may be running an Expanded Memory
Manager (such as EMM386).  This is because most machines running an EMM are
running it to get UMBs, and have the EMS support disabled.

My best advice is to write your actual program ignorant of what type of
memory is available.  Have it call a unit to deal with all of the dirty
details.  Your unit should then determine whether EMS is available or just
XMS, and use whichever one it can.  This is what I do, and it drastically
shortens development time of the main program.  The added benefit is that
you can reuse this unit with other programs.

The original XMS 2.0 specification allowed for 64 MB of XMS, because it
used a 16-bit register to pass block sizes in 1K increments.  With the 3.0
specification, extended 32-bit functions were added to allow XMS to go up
to 4 GB.  These functions require a 386 or better, but since you need a 386
or better to have more than 16 MB of RAM anyway, this does not matter.
