注册 登录
编程论坛 C图形专区

XMS内存为何申请失败?

ba_wang_mao 发布于 2006-12-08 11:50, 1295 次点击

由于我需要在操作画面上弹出一个窗口,因此必须将窗口覆盖区域的屏幕内容保存,由于常规内存紧张,因此决定在XMS内存中申请空间。
1、我检测了我的XMS空间总共有8000K,采用XMS_Size()函数检测的。
2、为保证显示速度及硬盘寿命,汉字库HZK16加载到XMS,占用260K。

当我再申请XMS空间比较小时,申请成功,而申请空间稍大时,却提示"XMS not enough"。如何解决申请比较大的空间呢(因为我有可能将整个屏幕800X600保存)?
//-----------------------------------------------------------
//检测XMS是否安装
//-----------------------------------------------------------
int _Cdecl XMS_Test(void)
{
_AX = 0x4300;
__int__(0x2F);
if (_AL == 0x80)
{
_AX = 0x4310;
__int__(0x2F);
XMS_Function=(void far *)MK_FP(_ES,_BX);
return (1);
}
return (-1);
}

//-----------------------------------------------------------
//查询空闲的扩充内存空间(不包括HMA)
//-----------------------------------------------------------
int _Cdecl XMS_Size(void)
{
_AH = 0x08;
XMS_Function();
return (_DX);
}

//-----------------------------------------------------------
//分配扩充内存
//-----------------------------------------------------------
int _Cdecl XMS_Alloc(int size)
{
_DX = size;
_AH = 0x09;
XMS_Function();
if(_AX == 1)
return (_DX);
return (-1);
}

//-----------------------------------------------------------
//汉字库hzk16装载到扩充内存
//-----------------------------------------------------------
void _Cdecl ReadHzkXMS(char *Hzkname)
{
unsigned long hzksize;
unsigned short size;
unsigned long offset = 0;
char buf[32];
FILE *fp;

if (XMS_Test() == -1)
{
puts("not found XMS");
exit(1);
}
if ((fp = fopen(Hzkname,"rb")) == NULL)
{
puts("Cannot Open HZK16 ...\n");
exit(1);
}
fseek(fp,0L,SEEK_END);
hzksize = ftell(fp);
fseek(fp,0L,SEEK_SET);
size = hzksize/1024 +1; // 262K
if (XMS_Size() < size)
{
puts("not enough XMS");
fclose(fp);
exit(-1);
}
if ((xms_handle = XMS_Alloc(size)) == 0)
{
puts("XMS handle Error...\n");
fclose(fp);
exit(-1);
}
while (!feof(fp))
{
size = fread(buf,sizeof(char),32,fp);
Write_To_XMS(buf,size,xms_handle,offset);//点阵字模移到XMS
offset += size;
}
fclose(fp);
}

//-----------------------------------------------------------
//将POPUP_x1,POPUP_y1,POPUP_x2,POPUP_y2
//包含区域的屏幕内容保存到XMS
//-----------------------------------------------------------
char XMSBuffer[800];
void _Cdecl Save_Image_XMS(void)
{
int i,j;
unsigned short size;
unsigned long offset = 0;
char *pp;

size = (POPUP_x2-POPUP_x1+1)*(POPUP_y2- POPUP_y1+1)/1024+1;
if (XMS_Size() < size)
puts("not enough XMS");
if ((xms_save_restore_handle = XMS_Alloc(size)) == 0)
puts("XMS handle Error...\n");
for (i= POPUP_y1; i<=POPUP_y2;i++)
{
size = POPUP_x2-POPUP_x1;
pp = XMSBuffer;
for (j= POPUP_x1; j<=POPUP_x2;j++)
*pp++ = getpixel(j,i);
Write_To_XMS(XMSBuffer,size,xms_save_restore_handle,offset);
offset += size;
}
}

void main()
{
ReadHzkXMS("HZK16");//汉字库hzk16装载到扩充内存
POPUP_x1 = 100;
POPUP_x2 = 550;
POPUP_y1 = 200;
POPUP_y2 = 500;
Save_Image_XMS();//此处提示申请XMS失败,而XMS空间有8000K
//而如果POPUP_x1 = 300 POPUP_y1 = 450 POPUP_x2 = 250
// POPUP_y2 = 450却能申请成功能?


11 回复
#2
一笔苍穹2006-12-08 13:11

去C盘的WINDOWS目录下找到一个名为_default的DOS程序快捷方式,点击属性,改为下图:

只有本站会员才能查看附件,请 登录

[此贴子已经被作者于2006-12-8 13:14:32编辑过]

#3
ba_wang_mao2006-12-08 14:02
我的程序是在纯DOS下,即MSDOS6.22下运行的。
#4
一笔苍穹2006-12-08 14:27
你看下你最多能分到多少?
#5
ba_wang_mao2006-12-08 14:32
我的程序是在纯DOS下,即MSDOS6.22下运行的。而且在CONFIG.SYS中加载了HIMEM.SYS。
  我为HZK16申请XMS空间时,句柄名为XMS_Handle,该空间常驻内存,直到程序退出才会释放。
  而当我为“窗口覆盖区域”申请XMS空间时,句柄名为XMS_Window,当窗口消失时,立即释放XMS_Window占用的XMS空间。

void main(void)
{
1、系统初始化 
    2、为HZK16申请XMS空间,将句柄号--->XMS_Handle。
  while (1)
{
if (如果有弹出式窗口需要弹出) then
{
为弹出式窗口申请XMS空间,将句柄号--->XMS_Window
}
else if (如果需要撤消弹出式窗口) then
{
则执行下述代码释放XMS_Window占用的XMS空间。
_DX = XMS_Window;
_AH = 0x0A;
XMS_Function();
}
}
}

  这个问题很急,谁能帮我解决呢?
#6
ba_wang_mao2006-12-08 16:47

我的程序必须在MSDOS6.22下运行的,且在CONFIG.SYS中加载了HIMEM.SYS。
  我为HZK16申请XMS空间时,句柄名为XMS_Handle,该空间常驻内存,直到程序退出才会释放。
  而当我为“窗口覆盖区域”申请XMS空间时,句柄名为XMS_Window,当窗口消失时,立即释放XMS_Window占用的XMS空间。
系统初始化时,我用以下代码查询可用XMS空间,得到8000K。
_AH = 0x08;
XMS_Function();

void main(void)
{
1、系统初始化 
    2、为HZK16申请XMS空间,将句柄号--->XMS_Handle。
  while (1)
{
if (如果有弹出式窗口需要弹出) then
{
执行下述代码为弹出式窗口申请XMS空间,将句柄号--->XMS_Window
_DX = size;
_AH = 0x09;
XMS_Function();
}
else if (如果需要撤消弹出式窗口) then
{
则执行下述代码释放XMS_Window占用的XMS空间。
_DX = XMS_Window;
_AH = 0x0A;
XMS_Function();
}
}
_DX = XMS_Handle;//程序退出,释放HZK16占用的XMS空间
_AH = 0x0A;
XMS_Function();
}

  这个问题很急,谁能帮我解决呢?

#7
一笔苍穹2006-12-08 17:43
你用NEO自带的XMS例程有这个问题么?
#8
ba_wang_mao2006-12-08 17:44
我试试
#9
一笔苍穹2006-12-08 17:50
记得在#include &lt;neo.h&gt;之前加上开关宏定义:#define NEO_xms_used
#10
ba_wang_mao2006-12-11 14:40

1、我用NEO程序XMS子程序做测试,并通过。
2、我程序中的XMS子程序做了个测试,也通过,说明程序无错误。
原来我的测试程序使用的是SMALL模式,而我的正式程序由于比较大因此使用的是HUGE模式(必须使用HUGE模式),请问要HUGE模式下如何解决XMS多次分配?

#11
ba_wang_mao2006-12-11 16:19

找到原因了,POPUP_x1,POPUP_y1,POPUP_y1,POPUP_y2为窗口的四个角坐标
1、原来定义为int size;
size = (POPUP_x2 - POPUP_x1 + 1 ) * (POPUP_y2 - POPUP_y1 +1 ) / 1024 + 1;
XMS_Alloc(size);//调用子程序分配XMS空间(以KB为单位)
2、现在更改为
int size;
long long_size;
long_size = ((long)POPUP_x2-(long)POPUP_x1+1)*((long)POPUP_y2-(long)POPUP_y1+1);
long_size = long_size/1024+1;
size = long_size;
XMS_Alloc(size);//调用子程序分配XMS空间(以KB为单位)

但是现在还有1个问题:
窗口最后一列无法恢复。源程序如下:


char XMSBuffer[800];
/*-----------------------------------------------------------
//保存窗口映像到XMS
-----------------------------------------------------------*/
void _Cdecl Save_Image_XMS(void)
{
int i,j;
unsigned int size;
long long_size;
unsigned long offset = 0;
char *pp;

long_size = ((long)POPUP_x2-(long)POPUP_x1+1)*
((long)POPUP_y2-(long)POPUP_y1+1);
long_size = long_size/1024+1;
size = long_size;
if (XMS_Size() > size)
{
if ((xms_window_handle = XMS_Alloc(size)) != 0)
{
size = POPUP_x2 - POPUP_x1;
for (i = POPUP_y1 ; i <= POPUP_y2 ; i++)
{
pp = XMSBuffer;
for (j = POPUP_x1 ; j <= POPUP_x2 ; j++)
*pp++ = getpixel(j,i);
Write_To_XMS(XMSBuffer,size,xms_window_handle,offset);
offset += size;
}
}
else
puts("XMS handle Error...\n");
}
else
puts("not enough XMS...\n");
}

/*-----------------------------------------------------------
//恢复窗口映像从XMS
-----------------------------------------------------------*/
void _Cdecl Restore_Image_XMS(void)
{
int i,j;
unsigned short size;
unsigned long offset = 0;
char *pp;

for (i = POPUP_y1 ; i <= POPUP_y2 ; i++)
{
size = POPUP_x2 - POPUP_x1;
Read_From_XMS(XMSBuffer,size,xms_window_handle,offset);
offset += size;
pp = XMSBuffer;
for (j = POPUP_x1 ; j <= POPUP_x2 ; j++)
putpixel(j,i,*pp++);
}
XMS_Free(xms_window_handle);
}

现在还有1个问题: 窗口最后一列无法恢复,为什么?

#12
一笔苍穹2006-12-11 17:38
最好不要用HUGE模式,HUGE和LARGE差别不大,编译出来的程序都可以一样大,只是HUGE的指针是可比的,LARGE的不可比而已。所以直接用LARGE就OK了,还有就是NEO中的函数可能跟HUGE合不太来。
要不你还可以使用BC++编译,开启覆盖模式,那样编译出来的程序可以有几M,因为它运行时是一块块的读入内存的,要下一块时就将以前读入但暂时没有用的块清除。不过只要TC的LARGE够用,尽量不用这个方案,因为反复的读写程序会导致执行性能的下降。
1