本篇给出XMS(扩充内存)内存TC函数汇编码文件,要使用XMS,必须安装驱动程序EMM386.EXE。注意,XMS与EMS(扩展内存)是2种不同的内存管理技术规范,由于它们对内存的管理范围有重叠,所以在驱动程序中应指明EMS的大小,如果全部1M外的内存全部都给了EMS,那么,XMS就只能管理UMB和HMA内存了,而这些内存还必须在DOS中配置才有,下面的配置保证了基本内存以外的内存全部由XMS管理:
device=himem.sys
device=emm386.exe noems
dos=high,umb
/*
XMS.H
*/
#ifndef__XMS_H
#define
__XMS_H
#define
XMS_MOVEFROM0
#define
XMS_MOVETO1
extern
int
XMS_Flag;
/*
XMS内存可使用标记,0不可使用,非0可使用
*/
#ifdef__cplusplus
extern
"
C
"
{
#endif
/*
定义使用XMS内存函数
*/
/*
测试XMS内存是否可用,将测试结果放在XMS_Flag,并返回XMS_Flag
*/
int
XMS_Init(
void
);
/*
返回最大XMS内存块字节数
*/
unsigned
long
XMS_GetFree(
void
);
/*
分配XMS内存,参数为字节数(长整型),成功返回内存块句柄,失败返回0
*/
unsignedXMS_Alloc(unsigned
long
);
/*
释放XMS内存块,参数位内存块句柄,成功返回1,失败返回0
*/
int
XMS_Free(unsigned);
/*
传输数据,参数:缓冲区;XMS句柄;XMS偏移量;字节数;传输标记,成功返回1,失败返回0
传输标记:XMS_MOVEFROM从XMS中取数据到缓冲区;
XMS_MOVETO将缓冲区数据送到XMS
*/
int
XMS_Move(
void
far
*
,unsigned,unsigned
long
,unsigned
long
,
int
);
#ifdef__cplusplue
}
#endif
#endif
XMS.ASM
P386N
includetasm_c.inc
XMS_MOVEFROMequ
0
XMS_MOVETOequ
1
DATASEG
PUBLIC_XMS_GetFree
PUBLIC_XMS_Alloc
PUBLIC_XMS_Move
PUBLIC_XMS_Free
PUBLIC_XMS_Init
PUBLIC_XMS_Flag
XMS_addrdd
0
_XMS_Flagdw
0
;
XMS_Bytesdd
0
XMS_SouHanddw
0
XMS_SouAddrdd
0
XMS_DesHanddw
0
XMS_DesAddrdd
0
;
CODESEG
;
;unsigned
long
XMS_GetFree(
void
)
;
PROC_XMS_GetFree
movah,
8
call[dwordXMS_addr]
movdx,ax
shlax,0ah
shrdx,06h
ret
ENDP
;
;
int
XMS_Init(
void
);
;
PROC_XMS_Init
movax,4300h
int
02fh
cmpal,80h
jne@@
1
movax,4310h
int
02fh
mov[wordXMS_addr
+
2
],es
mov[wordXMS_addr],bx
movah,
8
call[dwordXMS_addr]
mov[word_XMS_Flag],ax
jmp
short
@@
2
@@
1
:
mov[word_XMS_Flag],
0
xorax,ax
@@
2
:
ret
ENDP
;
;unsigned
int
XMS_Alloc(
long
size)
;
PROC_XMS_Alloc
ARGsize:dword
movax,[_XMS_Flag]
cmpax,
0
je@@
1
moveax,[dwordsize]
addeax,3ffh
shreax,0ah
movdx,ax
movah,
9
call[dwordXMS_addr]
cmpax,
0
jz@@
1
movax,dx
@@
1
:
ret
ENDP
;
;
int
XMS_Move(
void
far
*
buf,unsigned
long
ofs,unsigned
long
bytes,
int
flag)
;
PROC_XMS_Move
ARGbuf:farptr,handle:word,ofs:dword,bytes:dword,flag:word
USESsi
moveax,[dwordbytes]
mov[dwordXMS_Bytes],eax
cmp[wordflag],XMS_MOVEFROM
jne@@
1
movax,[handle]
mov[XMS_SouHand],ax
moveax,[dwordofs]
mov[XMS_SouAddr],eax
mov[wordXMS_DesHand],
0
moveax,[dwordbuf]
mov[dwordXMS_DesAddr],eax
jmp
short
@@
2
@@
1
:
mov[wordXMS_SouHand],
0
moveax,[dwordbuf]
mov[XMS_SouAddr],eax
movax,[handle]
mov[XMS_DesHand],ax
moveax,[dwordofs]
mov[dwordXMS_DesAddr],eax
@@
2
:
leasi,[XMS_Bytes]
movah,0bh
call[dwordES_XMS_addr]
ret
ENDP
;
;
int
XMS_Free(handle)
;
PROC_XMS_Free
ARGhandle:word
movah,0ah
movdx,[handle]
call[dwordXMS_addr]
ret
ENDP
;
END
上面的文件中使用的插入文件tasm_c.inc和编译文件在《Turbo C使用的汇编函数 -- VGA 12H模式图形函数(一)》中。本来想找个测试代码,可是代码确实太长(一个完整的程序),反正XMS函数调用也不复杂,也就免了。
连续几篇文章,将我十多年前自认为精华的代码全掏空了,从1998年,我就很少接触C/C++,虽说C/C++的代码还能看懂,也能写几句,但社会变化太快,近十年的时间不知改变了许多,有时候,我也用C/C++写点东西,但自从在Delphi版被一个自认为的C++“高手”的家伙所辱后,就没有再正二八经的用过“C++”(我其实是实话实说,说我不懂STL,也不喜欢它,他说,不懂STL就是不懂C++,当然还有他人帮腔也这么说,我只好无话可说了,原来我不用STL写的代码不能叫C++代码?!不过,偶尔也用BCB做点试验,反正BCB主要用VCL,极少用到STL)。幸好我只是个业余编程爱好者,不靠它吃饭!
再次声明,这几篇文章的代码是1995年前的东西,用现在的眼光去看它们,还不知道是不是C函数,只能供初学者们借鉴参考。至于是否有错误,我就不得而知了,不过,我以前使用时,没出过什么问题。有错误或建议,请来信:[email protected]