DOS程序使用XMS
概述:
      作为常规内存的扩充,XMS(即扩充内存)的应用很广泛,它主要用于程序的数据存储空间,使用XMS时,需要在常规内存中开一个缓冲区,然后用移动内存块的方法进行数据交换。
      XMS 内存的存取是通过 XMS 驱动程序进行的,存取 XMS 前,必须先检测 XMS 驱动程序是否存在,然后获取驱动程序地址,通过远调用来使用它。检测 
  XMS 及获取驱动程序地址通过 INT 2FH 的 4300H 和 4310H 功能来进行的,一旦成功后,所有对 XMS 的操作都是先在 AH 内设置功能码,然后通过对驱动程序进行 
  CALL FAR 来完成。在调用时需要在内存中先定义一个 EMM 结构,里面包括移动的字节数,XMS内存的句柄等要用到的参数。
有关资料:
  
  1.DOS 中断 2FH 的 4300H 及 4310H 功能
| 功能号 | 入口参数 | 出口参数 | 
| AX=4300H XMS安装检测  | 
    AL=80H 已安装XMS | |
| AL<>80H XMS未安装 | ||
| AX=4310H 取驱动程序地址  | 
    ES:BX=驱动程序入口地址 | 
2.远调用 XMS 驱动程序的功能表
| 功能号 | 入口参数 | 出口参数 | 
| AH=09H 分配XMS内存  | 
    DX=所需的KB | AX=0001H 成功 则DX=XMS 内存句柄  | 
  
| AX=0000H 失败 | ||
| AH=0AH 释放XMS内存  | 
    DX=XMS句柄 | AX=0001H 成功 | 
| AX=0000H 失败 | ||
| AH=0BH 移动XMS内存  | 
    DS:SI指向EMM结构 | AX=0001H 成功 | 
| AX=0000H 失败 | 
3.EMM 结构的格式
| 偏移量 | 大小 | 说明 | 
| 00H | Double word | 要移动的字节数(必须是偶数) | 
| 04H | Word | 源句柄(0 表示常规内存) | 
| 06H | Double word | 源块中的偏移量 | 
| 0AH | Word | 目的句柄(0 表示常规内存) | 
| 0CH | Double word | 目的块中的偏移量 | 
汇编编程示例: 
  
  
  ;定义 EMM 结构
  
  EMM     DW    0,0         
  ;double word -- how many bytes to move
          DW    0           
  ;word -- source handle
          DW    0,0         
  ;double word -- source offset & segment
          DW    0           
  ;word -- target handle
          DW    0,0         
  ;double word -- target offset & segment
  OFFXMS  DW    0           
  ;XMS驱动程序的入口地址
  SEGXMS  DW    0
  
  HANDLE_XMS    DW    0    ;申请到的XMS句柄
  
  
  ;以下程序检测及申请XMS内存
  
          mov    ax,4300h         
  ;检测有无XMS
          int    2fh
          cmp    al,80h
          jnz    no_xms
  
          mov    ax,4310h         
  ;保存XMS驱动程序地址
          int    2fh
          mov    offxms,bx
          mov    segxms,es
  
          mov    ah,9             
  ;分配XMS内存
          mov    dx,100           
  ;分配100KB
          call   dword ptr offxms
          or     ax,ax
          jz     no_more_xms 
       ;AX=0 则分配失败
  
          mov    xms_handle,dx
  
  ;以下程序将内存A000:0000处的64K字节移到XMS块中
  
          mov    emm,0
          mov    emm+2,1             
  ;10000H为64K
          mov    emm+4,0             
  ;source handle = 普通内存
          mov    emm+6,0             
  ;源地址A000:0000
          mov    emm+8,0a000h
          mov    bx,xms_handle
          mov    emm+0ah,bx 
           ;targat handle = XMS
          mov    emm+0ch,0           
  ;移动到XMS的起始地址
          mov    emm+0eh,0
          mov    si,offset emm
          mov    ah,0bh
          call   dword ptr offxms
  
  ;以下程序将XMS块中的64K字节移到内存A000:0000处
  
          mov    emm,0
          mov    emm+2,1             
  ;bytes = 10000H (64K)
          mov    bx,xms_handle
          mov    emm+4,bx            
  ;source handle
          mov    emm+6,0             
  ;source offset
          mov    emm+8,0
          mov    emm+0ah,0           
  ;target handle 0 for MEM
          mov    emm+0ch,0           
  ;target offset
          mov    emm+0eh,0a000h
          mov    si,offset emm
          mov    ah,0bh
          call   dword ptr offxms
  
  ;以下程序释放XMS内存
  
          mov    ah,0ah             
  ;free XMS memory
          mov    dx,cs:xms_handle
          call   dword ptr cs:offxms