ba_wang_mao 发表于 2006-12-8 11:50

XMS内存为何申请失败?

<P>由于我需要在操作画面上弹出一个窗口,因此必须将窗口覆盖区域的屏幕内容保存,由于常规内存紧张,因此决定在XMS内存中申请空间。<BR>1、我检测了我的XMS空间总共有8000K,采用XMS_Size()函数检测的。<BR>2、为保证显示速度及硬盘寿命,汉字库HZK16加载到XMS,占用260K。<BR><BR>当我再申请XMS空间比较小时,申请成功,而申请空间稍大时,却提示"XMS not enough"。如何解决申请比较大的空间呢(因为我有可能将整个屏幕800X600保存)?<BR>//-----------------------------------------------------------<BR>//检测XMS是否安装<BR>//-----------------------------------------------------------<BR>int _Cdecl XMS_Test(void)<BR>{<BR>    _AX = 0x4300;<BR>    __int__(0x2F);<BR>    if (_AL == 0x80)<BR>    {<BR>        _AX = 0x4310;<BR>        __int__(0x2F);<BR>        XMS_Function=(void far *)MK_FP(_ES,_BX);<BR>        return (1);<BR>    }<BR>    return (-1);<BR>}</P>
<P>//-----------------------------------------------------------<BR>//查询空闲的扩充内存空间(不包括HMA)<BR>//-----------------------------------------------------------<BR>int _Cdecl XMS_Size(void)<BR>{<BR>    _AH = 0x08;<BR>    XMS_Function();<BR>    return (_DX);<BR>}</P>
<P>//-----------------------------------------------------------<BR>//分配扩充内存<BR>//-----------------------------------------------------------<BR>int _Cdecl XMS_Alloc(int size)<BR>{<BR>    _DX = size;<BR>    _AH = 0x09;<BR>    XMS_Function();<BR>    if(_AX == 1)<BR>        return (_DX);<BR>    return (-1);<BR>}</P>
<P>//-----------------------------------------------------------<BR>//汉字库hzk16装载到扩充内存<BR>//-----------------------------------------------------------<BR>void _Cdecl ReadHzkXMS(char *Hzkname)<BR>{<BR>    unsigned long hzksize;<BR>    unsigned short size;<BR>    unsigned long offset = 0;<BR>    char buf[32];<BR>    FILE *fp;</P>
<P>    if (XMS_Test() == -1)<BR>    {<BR>        puts("not found XMS");<BR>        exit(1);<BR>    }<BR>    if ((fp = fopen(Hzkname,"rb")) == NULL)<BR>    {<BR>        puts("Cannot Open HZK16 ...\n");<BR>        exit(1);<BR>    }<BR>    fseek(fp,0L,SEEK_END);<BR>    hzksize = ftell(fp);<BR>    fseek(fp,0L,SEEK_SET);<BR>    size = hzksize/1024 +1;        // 262K<BR>   if (XMS_Size() &lt; size)<BR>    {<BR>        puts("not enough XMS");<BR>        fclose(fp);<BR>        exit(-1);<BR>    }<BR>    if ((xms_handle = XMS_Alloc(size)) == 0)<BR>    {<BR>        puts("XMS handle Error...\n");<BR>        fclose(fp);<BR>        exit(-1);<BR>    }<BR>    while (!feof(fp))<BR>    {<BR>        size = fread(buf,sizeof(char),32,fp);<BR>        Write_To_XMS(buf,size,xms_handle,offset);//点阵字模移到XMS<BR>        offset += size;<BR>    }<BR>    fclose(fp);<BR>}<BR><BR>//-----------------------------------------------------------<BR>//将POPUP_x1,POPUP_y1,POPUP_x2,POPUP_y2<BR>//包含区域的屏幕内容保存到XMS<BR>//-----------------------------------------------------------<BR>char XMSBuffer[800];<BR>void _Cdecl Save_Image_XMS(void)<BR>{<BR>    int i,j;<BR>    unsigned short size;<BR>    unsigned long offset = 0;<BR>    char *pp;</P>
<P>    size = (POPUP_x2-POPUP_x1+1)*(POPUP_y2-    POPUP_y1+1)/1024+1;<BR>    if (XMS_Size() &lt; size)<BR>        puts("not enough XMS");<BR>    if ((xms_save_restore_handle = XMS_Alloc(size)) == 0)<BR>        puts("XMS handle Error...\n");<BR>    for (i= POPUP_y1; i&lt;=POPUP_y2;i++)<BR>    {<BR>        size = POPUP_x2-POPUP_x1;<BR>        pp = XMSBuffer;<BR>        for (j= POPUP_x1; j&lt;=POPUP_x2;j++)<BR>            *pp++ = getpixel(j,i);<BR>        Write_To_XMS(XMSBuffer,size,xms_save_restore_handle,offset);<BR>        offset += size;<BR>    }<BR>}<BR><BR>void main()<BR>{<BR>    ReadHzkXMS("HZK16");//汉字库hzk16装载到扩充内存<BR>    POPUP_x1 = 100;<BR>    POPUP_x2 = 550;<BR>    POPUP_y1 = 200;<BR>    POPUP_y2 = 500;<BR>    Save_Image_XMS();//此处提示申请XMS失败,而XMS空间有8000K<BR>    //而如果POPUP_x1 = 300 POPUP_y1 = 450  POPUP_x2 = 250<BR>   // POPUP_y2 = 450却能申请成功能?<BR><BR><BR></P>

一笔苍穹 发表于 2006-12-8 13:11

<P>去C盘的WINDOWS目录下找到一个名为_default的DOS程序快捷方式,点击属性,改为下图:<br></P>[attach]14595[/attach]<br>
[align=right][color=#000066][此贴子已经被作者于2006-12-8 13:14:32编辑过][/color][/align]

ba_wang_mao 发表于 2006-12-8 14:02

我的程序是在纯DOS下,即MSDOS6.22下运行的。

一笔苍穹 发表于 2006-12-8 14:27

你看下你最多能分到多少?

ba_wang_mao 发表于 2006-12-8 14:32

我的程序是在纯DOS下,即MSDOS6.22下运行的。而且在CONFIG.SYS中加载了HIMEM.SYS。<BR>  我为HZK16申请XMS空间时,句柄名为XMS_Handle,该空间常驻内存,直到程序退出才会释放。<BR>  而当我为“窗口覆盖区域”申请XMS空间时,句柄名为XMS_Window,当窗口消失时,立即释放XMS_Window占用的XMS空间。<BR><BR>    void main(void)<BR>    {<BR>       1、系统初始化 <BR>    2、为HZK16申请XMS空间,将句柄号---&gt;XMS_Handle。<BR>      while (1)<BR>       {<BR>            if (如果有弹出式窗口需要弹出) then<BR>            {<BR>                 为弹出式窗口申请XMS空间,将句柄号---&gt;XMS_Window<BR>            }<BR>            else if (如果需要撤消弹出式窗口) then<BR>            {<BR>                 则执行下述代码释放XMS_Window占用的XMS空间。<BR>                _DX = XMS_Window;<BR>                _AH = 0x0A;<BR>                XMS_Function();<BR>             } <BR>        }<BR>    }<BR><BR>  这个问题很急,谁能帮我解决呢?

ba_wang_mao 发表于 2006-12-8 16:47

<P>我的程序必须在MSDOS6.22下运行的,且在CONFIG.SYS中加载了HIMEM.SYS。<BR>  我为HZK16申请XMS空间时,句柄名为XMS_Handle,该空间常驻内存,直到程序退出才会释放。<BR>  而当我为“窗口覆盖区域”申请XMS空间时,句柄名为XMS_Window,当窗口消失时,立即释放XMS_Window占用的XMS空间。<BR>    系统初始化时,我用以下代码查询可用XMS空间,得到8000K。<BR>        _AH = 0x08;<BR>        XMS_Function();</P>
<P>    void main(void)<BR>    {<BR>       1、系统初始化 <BR>    2、为HZK16申请XMS空间,将句柄号---&gt;XMS_Handle。<BR>      while (1)<BR>       {<BR>            if (如果有弹出式窗口需要弹出) then<BR>            {<BR>                 执行下述代码为弹出式窗口申请XMS空间,将句柄号---&gt;XMS_Window<BR>                _DX = size;<BR>                _AH = 0x09;<BR>                XMS_Function();<BR>            }<BR>            else if (如果需要撤消弹出式窗口) then<BR>            {<BR>                 则执行下述代码释放XMS_Window占用的XMS空间。<BR>                _DX = XMS_Window;<BR>                _AH = 0x0A;<BR>                XMS_Function();<BR>             } <BR>        }<BR>        _DX = XMS_Handle;//程序退出,释放HZK16占用的XMS空间<BR>        _AH = 0x0A;<BR>        XMS_Function();<BR>    }</P>
<P>  这个问题很急,谁能帮我解决呢?</P>

一笔苍穹 发表于 2006-12-8 17:43

你用NEO自带的XMS例程有这个问题么?

ba_wang_mao 发表于 2006-12-8 17:44

我试试<BR>

一笔苍穹 发表于 2006-12-8 17:50

记得在#include &lt;neo.h&gt;之前加上开关宏定义:#define NEO_xms_used

ba_wang_mao 发表于 2006-12-11 14:40

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

ba_wang_mao 发表于 2006-12-11 16:19

<P>找到原因了,POPUP_x1,POPUP_y1,POPUP_y1,POPUP_y2为窗口的四个角坐标<BR>1、原来定义为int size;<BR>   size = (POPUP_x2 - POPUP_x1 + 1 ) * (POPUP_y2 - POPUP_y1 +1 ) / 1024 + 1;<BR>   XMS_Alloc(size);//调用子程序分配XMS空间(以KB为单位)<BR>2、现在更改为<BR>    int size;<BR>    long long_size;<BR>    long_size = ((long)POPUP_x2-(long)POPUP_x1+1)*((long)POPUP_y2-(long)POPUP_y1+1);<BR>    long_size = long_size/1024+1;<BR>    size = long_size;<BR>    XMS_Alloc(size);//调用子程序分配XMS空间(以KB为单位)<BR><BR>但是现在还有1个问题:<BR>    窗口最后一列无法恢复。源程序如下:<BR><BR><BR>char XMSBuffer[800];<BR>/*-----------------------------------------------------------<BR>//保存窗口映像到XMS<BR>-----------------------------------------------------------*/<BR>void _Cdecl Save_Image_XMS(void)<BR>{<BR>    int i,j;<BR>    unsigned int size;<BR>    long long_size;<BR>    unsigned long offset = 0;<BR>     char *pp;</P>
<P>    long_size = ((long)POPUP_x2-(long)POPUP_x1+1)*<BR>                ((long)POPUP_y2-(long)POPUP_y1+1);<BR>    long_size = long_size/1024+1;<BR>    size = long_size;<BR>    if (XMS_Size() &gt; size)<BR>    {<BR>        if ((xms_window_handle = XMS_Alloc(size)) != 0)<BR>        {<BR>            size = POPUP_x2 - POPUP_x1;<BR>            for (i = POPUP_y1 ; i &lt;= POPUP_y2 ; i++)<BR>            {<BR>                pp = XMSBuffer;<BR>                for (j = POPUP_x1 ; j &lt;= POPUP_x2 ; j++)<BR>                    *pp++ = getpixel(j,i);<BR>                Write_To_XMS(XMSBuffer,size,xms_window_handle,offset);<BR>                offset += size;<BR>            }<BR>        }<BR>        else<BR>            puts("XMS handle Error...\n");<BR>    }<BR>    else<BR>        puts("not enough XMS...\n");<BR>}<BR><BR>/*-----------------------------------------------------------<BR>//恢复窗口映像从XMS<BR>-----------------------------------------------------------*/<BR>void _Cdecl Restore_Image_XMS(void)<BR>{<BR>    int i,j;<BR>    unsigned short size;<BR>    unsigned long offset = 0;<BR>    char *pp;</P>
<P>    for (i = POPUP_y1 ; i &lt;= POPUP_y2 ; i++)<BR>    {<BR>        size = POPUP_x2 - POPUP_x1;<BR>        Read_From_XMS(XMSBuffer,size,xms_window_handle,offset);<BR>        offset += size;<BR>        pp = XMSBuffer;<BR>        for (j = POPUP_x1 ; j &lt;= POPUP_x2 ; j++)<BR>            putpixel(j,i,*pp++);<BR>    }<BR>    XMS_Free(xms_window_handle);<BR>}<BR><BR>现在还有1个问题: 窗口最后一列无法恢复,为什么?</P>

一笔苍穹 发表于 2006-12-11 17:38

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

页: [1]

编程论坛