本篇给出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
#ifndef __XMS_H
#define __XMS_H
#define XMS_MOVEFROM 0
#define XMS_MOVETO 1
extern " C " {
#endif
/* 定义使用 XMS 内存函数 */
/* 测试 XMS 内存是否可用, 将测试结果放在 XMS_Flag, 并返回 XMS_Flag */
int XMS_Init( void );
/* 返回最大 XMS 内存块字节数 */
unsigned long XMS_GetFree( void );
/* 分配 XMS 内存, 参数为字节数(长整型), 成功返回内存块句柄, 失败返回 0 */
unsigned XMS_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 );
}
#endif
#endif
P386N
include tasm_c.inc
XMS_MOVEFROM equ 0
XMS_MOVETO equ 1
DATASEG
PUBLIC _XMS_GetFree
PUBLIC _XMS_Alloc
PUBLIC _XMS_Move
PUBLIC _XMS_Free
PUBLIC _XMS_Init
PUBLIC _XMS_Flag
XMS_addr dd 0
_XMS_Flag dw 0
;
XMS_Bytes dd 0
XMS_SouHand dw 0
XMS_SouAddr dd 0
XMS_DesHand dw 0
XMS_DesAddr dd 0
;
CODESEG
;
; unsigned long XMS_GetFree( void )
;
PROC _XMS_GetFree
mov ah, 8
call [dword XMS_addr]
mov dx, ax
shl ax, 0ah
shr dx, 06h
ret
ENDP
;
; int XMS_Init( void );
;
PROC _XMS_Init
mov ax, 4300h
int 02fh
cmp al, 80h
jne @@ 1
mov ax, 4310h
int 02fh
mov [word XMS_addr + 2 ], es
mov [word XMS_addr], bx
mov ah, 8
call [dword XMS_addr]
mov [word _XMS_Flag], ax
jmp short @@ 2
@@ 1 :
mov [word _XMS_Flag], 0
xor ax, ax
@@ 2 :
ret
ENDP
;
; unsigned int XMS_Alloc( long size)
;
PROC _XMS_Alloc
ARG size : dword
mov ax, [_XMS_Flag]
cmp ax, 0
je @@ 1
mov eax, [dword size]
add eax, 3ffh
shr eax, 0ah
mov dx, ax
mov ah, 9
call [dword XMS_addr]
cmp ax, 0
jz @@ 1
mov ax, dx
@@ 1 :
ret
ENDP
;
; int XMS_Move( void far * buf, unsigned long ofs, unsigned long bytes, int flag)
;
PROC _XMS_Move
ARG buf : far ptr, handle : word, ofs : dword, bytes : dword, flag : word
USES si
mov eax, [dword bytes]
mov [dword XMS_Bytes], eax
cmp [word flag], XMS_MOVEFROM
jne @@ 1
mov ax, [handle]
mov [XMS_SouHand], ax
mov eax, [dword ofs]
mov [XMS_SouAddr], eax
mov [word XMS_DesHand], 0
mov eax, [dword buf]
mov [dword XMS_DesAddr], eax
jmp short @@ 2
@@ 1 :
mov [word XMS_SouHand], 0
mov eax, [dword buf]
mov [XMS_SouAddr], eax
mov ax, [handle]
mov [XMS_DesHand], ax
mov eax, [dword ofs]
mov [dword XMS_DesAddr], eax
@@ 2 :
lea si, [XMS_Bytes]
mov ah, 0bh
call [dword ES_ XMS_addr]
ret
ENDP
;
; int XMS_Free(handle)
;
PROC _XMS_Free
ARG handle : word
mov ah, 0ah
mov dx, [handle]
call [dword XMS_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函数,只能供初学者们借鉴参考。至于是否有错误,我就不得而知了,不过,我以前使用时,没出过什么问题。有错误或建议,请来信:maozefa@hotmail.com