使用XMS扩展内存编程实例
2010-11-04 13:47
344 查看
粗略地讲,扩展内存和扩充内存在物理上都是指高内存区,只是由于管理程序的不同而给予不同的称呼,二者分别代表了两种不同的管理规范:EMS和XMS。它们以不同的方式提供了使用高内存的操作。二者都是在系统启动时加载驱动程序而控制高内存的,并为用户提供功能调用。
二者的另一相似之处都是采用句柄的方法进行管理。用户程序申请一块高内存,得到的是一个句柄,对此高内存块的访问都是通过这个句柄来完成的,用户程序调用管理规范提供的功能实现对此高内存块操作。
使用XMS,应在CONFIG.SYS文件中加入:
DEVICE=C:/DOS/HIMEM.SYS /MEMTEST:OFF
DEVICE=C:/DOS/EMM386.EXE /NOEMS
程序实例:
二者的另一相似之处都是采用句柄的方法进行管理。用户程序申请一块高内存,得到的是一个句柄,对此高内存块的访问都是通过这个句柄来完成的,用户程序调用管理规范提供的功能实现对此高内存块操作。
使用XMS,应在CONFIG.SYS文件中加入:
DEVICE=C:/DOS/HIMEM.SYS /MEMTEST:OFF
DEVICE=C:/DOS/EMM386.EXE /NOEMS
程序实例:
#include <mem.h> #ifndef XRH_XMS_LIBRARY #define XRH_XMS_LIBRARY #include <DOS.H> #include <STDIO.H> #include <STDLIB.H> struct XMS_Move_Data{ unsigned long far Move_Bytes; // 移动的字节数 unsigned far Source_Handle; // 源句柄 unsigned long far Source_Offset; // 源偏移量 unsigned far Target_Handle; // 目的句柄 unsigned long far Target_Offset; // 目的偏移量 }; int far XMS=0; class MyXMS{ private: int XMS; int Xms_Err; int IsErr(int Xms_Err_Num); void (far *Xms)(void); void XMS_Get_Drive_Addr(void); static int MyXMS_Num; public: XMS_Move_Data Xmd; // very important, the detail at above int XMS_Check(unsigned &Max_Block_Size,unsigned &Total_Size); int XMS_Get(unsigned &Handle,unsigned Size); int XMS_ReGet(unsigned Handle,unsigned ReSize); int XMS_Free(unsigned Handle); int XMS_Move(); // 设置好了结构体 Xmd 之后,主动调用本函数,可实现数据块的移动 int base_to_xms(void far *base,unsigned handle,unsigned long length,unsigned long emboffset); int xms_to_base(void far *base,unsigned handle,unsigned long length,unsigned long emboffset); MyXMS(); ~MyXMS(); }; int MyXMS::MyXMS_Num=0; // XMS (Int 2F/43) 多路中断 // INT 2F - XMS 驱动程序安装检测 // 输入参数:AX = 4300h // 返回值: AL = 80h XMS 驱动程序已安装 // AL <> 80h 未发现XMS 驱动程序 // 注: XMS 使你可以访问扩充内存以及其它的高于640K的非EMS内存 // 其它程序不得使用与之相同的安装检测方式 int XMS_Test(void) { asm { mov ax ,0x4300 int 0x2F } if(_AL==0x80) XMS=1; else XMS=0; return XMS; } // 错误代码 // 80h 没有提供的功能 // 81h 检测到虚拟盘(Vdisk) // 82h 发生A20地址线错误 // 8Eh 一般驱动程序错误 // 8Fh 致命的驱动程序错误 // 90h 高端内存(HMA)不存在 // 91h 高端内存(HMA)已被使用 // 92h DX is less than the /HMAMIN= parameter // 93h 高端内存(HMA)未被分配 // 94h A20地址线已被激活 // A0h 所有扩充内存已被分配 // A1h 所有可用的句柄已被分配 // A2h 无效的句柄 // A3h 无效的源句柄 // A4h 无效的源偏移 // A5h 无效的目的句柄 // A6h 无效的目的偏移 // A7h 无效的长度 // A8h 移动有非法的重叠 // A9h 发生奇偶校验错误 // AAh 块未加锁 // ABh 块已被锁定 // ACh 块锁定计数溢出 // ADh 锁定失败 // B0h 只有更小一些的UMB空间 // B1h 没有可用的UMB空间 int MyXMS::IsErr(int Xms_Err_Num) { switch(Xms_Err_Num) { case 0x80: case 0x81: case 0x82: case 0x8E: case 0x8F: case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7: case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xB0: case 0xB1: return 1; default : return 0; } } // INT 2F - XMS - 获取驱动程序入口地址 // 输入参数:AX = 4310h // 返回值: ES:BX -> 驱动程序入口地址 // 请参见: AX=4300h // AH中放功能号, 用远调用的方式调用驱动程序 // BL中返回的错误代码 void MyXMS::XMS_Get_Drive_Addr() { if (XMS) { asm { mov ax,0x4310 int 0x2F } this->Xms=(void (far *)())(((unsigned long)(_ES)<<16)+_BX); // Xms=(void (far *)())(((unsigned long)(_ES)<<16)+_BX); } return; } // 查询空闲的扩充内存空间, 不包括HMA // 输入参数:AH = 08h // 返回值: AX = 最大的扩充内存块的大小(单位:K) // DX = 总的扩充内存块的大小(单位:K) // BL = 错误代码 int MyXMS::XMS_Check(unsigned &Max_Block_Size,unsigned &Total_Size) { if (XMS) { asm mov ah,0x08 Xms(); Max_Block_Size=_AX; Total_Size=_DX; Xms_Err=_BL; } return (!(IsErr(Xms_Err))); } // 分配扩充内存 // 输入参数:AH = 09h // DX = 要求分配的内存块大小(单位:K) // 返回值: AX = 0001h 成功 // DX = 内存块的句柄 // AX = 0000h 失败 // BL = 错误代码 int MyXMS::XMS_Get(unsigned &Handle,unsigned Size) { unsigned Ax=0; if (XMS) { asm { mov ah,0x09 mov dx,Size } Xms(); Ax=_AX; Handle=_DX; Xms_Err=_BL; if(!Ax) return 0; return 1; } return 0; // return(!(IsErr(Xms_Err))); } // 为句柄重新分配内存 // 输入参数:AH = 0Fh // DX = 句柄 // BX = 新的块的容量(单位:K) // 返回值: AX = 0001h 成功 // = 0000h 失败 // BL = 错误代码 int MyXMS::XMS_ReGet(unsigned Handle,unsigned ReSize) { unsigned Ax=0; if (XMS) { asm { mov ah,0x0F mov dx,Handle mov bx,ReSize } Xms(); Ax=_AX; Xms_Err=_BL; if(!Ax) return 0; return 1; } return 0; } // 释放指定句柄所分配的扩充内存 // 输入参数:AH = 0Ah // DX = 内存块的句柄 // 返回值: AX = 0001h 成功 // = 0000h 失败 // BL = 错误代码 int MyXMS::XMS_Free(unsigned Handle) { unsigned Ax=0; if (XMS) { asm { mov ah,0x0A mov dx,Handle } Xms(); Ax=_AX; Xms_Err=_BL; if(!Ax) return 0; return 1; } return 0; // return(!(IsErr(Xms_Err))); } // 移动扩充内存块 // 输入参数:AH = 0Bh // DS:SI -> xms_mov 结构 // 返回值: AX = 0001h 成功 // = 0000h 失败 // BL = 错误代码 // 注: 如果结构中任一句柄为0000h, 那么其对应32位偏移量将被视为常规内存 // 的绝对地址 int MyXMS::XMS_Move() { unsigned Ax=0; if (XMS) { asm push ds; unsigned Xseg=FP_SEG(&(this->Xmd)),Xoff=FP_OFF(&(this->Xmd)); asm { mov ah,0x0B mov si,Xoff mov ds,Xseg } Xms(); asm pop ds; Ax=_AX; Xms_Err=_BL; if(!Ax) return 0; return 1; } return 0; } int MyXMS::base_to_xms(void far *base,unsigned handle,unsigned long length,unsigned long emboffset) { unsigned seg,off; unsigned long offset; seg=FP_SEG(base); off=FP_OFF(base); offset=(((unsigned long)seg)<<16)+off; Xmd.Move_Bytes=length; //长度必须是偶数 Xmd.Source_Handle=0; //句柄=0时,由下面的Offset给出地址 Xmd.Source_Offset=offset; Xmd.Target_Handle=handle; Xmd.Target_Offset=emboffset; if(!XMS_Move()) return 0; else return 1; } int MyXMS::xms_to_base(void far *base,unsigned handle,unsigned long length,unsigned long emboffset) { unsigned seg,off; unsigned long offset; seg=FP_SEG(base); off=FP_OFF(base); offset=(((unsigned long)seg)<<16)+off; Xmd.Move_Bytes=length; //长度必须是偶数 Xmd.Source_Handle=handle; Xmd.Source_Offset=emboffset; Xmd.Target_Handle=0; //句柄=0时,由下面的Offset给出地址 Xmd.Target_Offset=offset; if(!XMS_Move()) return 0; else return 1; } MyXMS::MyXMS() { Xms_Err=0; if (!MyXMS_Num) ::XMS_Test(); XMS=::XMS; if(!XMS){printf(" XMS Not Found,Please Setup In 'Config.sys' File.");exit(1);} MyXMS_Num++; XMS_Get_Drive_Addr(); } MyXMS::~MyXMS() { MyXMS_Num--; } #endif void main() { MyXMS myxms; char buff[32000]; memset(buff,'A',19); buff[19]='/0'; printf("/nbuff=%s",buff); unsigned handle=0; unsigned size=10; //10kb if(!myxms.XMS_Get(handle,size)) //先申请XMS内存得到句柄handle { //size的单位是kb printf("/nget memory error!"); return; } if(!myxms.base_to_xms(buff,handle,8,0)) //从基本内存移动8个字节到XMS内存 { //长度必须是偶数 printf("/nbase to xms error!"); myxms.XMS_Free(handle); } memset(buff,'0',19); printf("/nbuff=%s",buff); myxms.xms_to_base(buff,handle,8,0); printf("/nbuff=%s",buff); myxms.XMS_Free(handle); }
相关文章推荐
- DOS中使用扩展内存与XMS操作库设计
- 通过实例谈C#对象对内存的使用
- 使用memory_profiler 与 cProfile ,line_profiler 优化Python程序运行时间和内存消耗实例
- linux 使用sock编程实例
- 举例讲解C#编程中委托的实例化使用
- 使用W“.NET技术”CF实现SOA面向服务编程——简单的WCF开发实例
- Spring 整合Shiro 并扩展使用EL表达式的实例详解
- 初学Python的学习笔记9----面向对象编程(获取对象信息、实例属性和类属性)、面向对象高级编程(使用__slots__、使用@property)
- EXTJS4扩展实例:如何使用filter查询treepanel
- Socket编程基础-使用实例源码
- Python使用稀疏矩阵节省内存实例
- Java内存的一点理解, 静态方法和实例方法的区别及使用场景
- hadoop中使用MapReduce编程实例(转)
- 使用Java进行SNMP编程-SNMP4J-SNMPv3-代码实例
- ie下使用扩展canvas的javascript图形编程
- WindowsPhone App如何扩展能够使用的内存
- 编程获取linuxservercpu、内存和磁盘使用
- python网络编程之TCP通信实例和socketserver框架使用例子
- hadoop中使用MapReduce编程实例(转)
- Python编程之列表操作实例详解【创建、使用、更新、删除】