主题:[精华]一种标准的TSR标识技术
-= 附录C 一种标准的TSR标识技术 =-
对于在同一时间里同时使用几种TSR程序来说,长期以来一直存在着一个问题,这
就是:当这些程序之间出现冲突时,我们找不到任何可遵循的标准来管理冲突。
早在1986年,一大群TSR开发者组织起了一支队伍,旨在建立这样一种标准。大多
数在TSR开发上居于领导地位的开发者参加了这一组织。
然而,在经过首次努力尝试以生产出一种可供独家程序和商业化程序使用的完整应
用程序接口(这种努力未能得到商用TSR出版部门的足够支持)之后的一段时间时,许多
成员离开了这一队伍,并转而从事其它方面的研究工作。不过,他们在共同研究期间已开
发并发行了一种接口,该接口允许开发者与他们自己的(或其它人的)TSR进行通信,此
外,他们的设计部门还把用于Microsoft和Turbo C、TurboPascal版本4和版本5以及汇
编语言程序的原有例程库(即众所周知的TesSeRact)设计成了一种可用的共享件。
TesSeRact标准指定了一组链接着DOS的多路复用中断(2Fh)的功能。由于DOs使
用这种中断来与其自己的TSR(如ASSIGN、PRINT和SHARE)通信,因此,TesSeRact
开发队伍感到最合适的方法是用相同的接口来服务于不同的TSR程序。并且通过把AX
设置为某个特殊代码(5453h或ASCII中的TS)来调用中断2Fh便可访问这些TesSeRact
功能。
但这种用法与已公开的Int 2Fh标准用法不相符,在采用标准用法时,DOS规定:标
识代码必须在AH寄存器中(并在80h-FFh范围内),AL=0表示该中断用于已“安装
否?”的功能。
在公开TesSeRact的正式用法之前,这支开发队伍已开发出了TesSeRact的标准,并
且初始拷贝的用途太广泛了,以致不允许对这样一种基本特征作出改变。不相容性也不会
造成任何问题,因为目前尚不知道哪个功能当前正使用54h代码(即使有程序在使用,那
么它还同时拥有53h功能的机会几乎没有)。
还值得一提的是,自从版本3.3引入了APPEND之后,DOS就开始不遵循它自己的
规则;它使用了B7h代码,而这个代码的正式身份是作为非DOS应用程序的保留代码。
为了实现减少不同来源的TSR之间彼此产生的冲突这一原始目标,这支开发队伍还
鼓励所有开发者在各自的代码中支持TesSeRact标准。具体做法是通过开发一个用于Int
2Fh的处理程序,以便支持用户参数块和本附录将通过特殊的TS标识代码来介绍的两
种功能。
C.1用户参数块
与TesSeRact兼容的要求之一是必须支持UserParms数据区。该区域的描述如下(这
一区域必须处在用于Int 2Fh的TSR处理程序的开头):
New_2F: Jmp 0verParms ; Int 2F vector points here
UserParms db 8 dup l(' ') ; 8-byte Program ID string
IdNum dw 0 ; TSR identification number
FuncFlag dd 0ffffffffh ; supported function bit map
HotKey db 0 ; scan code of hot key to use
ShiftSt db 0 ; shift state to use for popup
HotFlag db 0 ;which hot key iS in use
ExtCnt db0 ; number of extmhot keys
ExtHot dd 0 ; pointer to extra hot keys
Status dw 0 ; TSR Status flags
OurPSP dw 0 ; ourPSP segment
ourDTA dd 0 ; our DTA region
DSeg dw 0 ; user's default data Segment
注意,这里仅仅只是列举该数据区结构的一部分;而没有列举由TesSeRact库保持并
使用的元素。
FuncFlag是一个位映象的4字节变量,显示着TSR所支持的所有多路复用功能。每
当调用这种功能时,必须通过BX把其功能号传送给处理程序,而不是像标准情况下通过
AL来传送,其原因我们曾解释过。该变量的映象如下:
位 0 功能00h(检查安装—必需功能)
位1 功能01h(返回用户参数—必需功能)
位2 功能02h(检查热键)
位3 功能03h(置换INT24h)
位4 功能04N(返回数据指针)
位5 功能05h(设置附加热键)
位6-7 未定义—留待将来使用
位8 功能10h(允许TSR)
位9 功能11h(禁止TSR)
位10 功能12h(从RAM中释放TSR)
位11 功能13h(重新启动TSR)
位12 功能14h(获取当前状态)
位13 功能15h(设置TSR状态)
位14 功能16h(获取弹出式打印)
位15 未定义 —留待将来使用
位16 功能20h(调用用户进程)
位17 功能21h(填充键盘缓冲区)
位18- 31 未定义—留待将来使用
如果TSR支持所用的功能,那么必须把对应的位置为1,否则必须将其置为0,使用
TesSeRact库例库的程序在返回时会把FuneFlag置为FFFFFFFFh。其它的TSR则必须
把未定义的变量设置为0,以便同它们自己的变量区别开来。
C.2功能00h(检查安装)
检查安装(功能00h)可确定系统是否安装了某个程序。该功能可通过以下方式来调
用:
mov ax , 5453h ; TS code
mov si , offset IDStr ; see below
mov ds,seg IDStr
xor cx ,cx ; handle counter
xor bx,bX ; function 0000
int 2Fh
IDStr是一个8字节数据区,它保存着一个独一无二的TSR标识符串。 Int 2Fh例程
必须把传送给它的字符串(如下例所示)与它自己的8字节字符串进行比较。如果这两个
字符串相符合,TSR在返回时就必须把CX设置为它自己的TSR句柄,并把AX寄存器
设置为0FFFFFh。
如果标识字符串与传送的字符串不匹配,那么TSR应恢复所有寄存器,增加一个cx
寄存器,并继续沿着程序链往下传送中断。在使用该功能时如果在链接到下一个TSR之
前,系统中每个TesSeRact兼容的TSR都增加了一个CX寄存器,而在此时,中断进程又
实际上返回到调用者这边,那么在这种时候,CX寄存器要么为被找到的TSR的句柄,或
者在没有找到与IDStr相匹配的TSR时为下一个可用的句柄。
如果没有能找到匹配,在返回时AL就不会等于FFh;这样,TSR安装程序就可把
CX的内容用作句柄,以通过它来进行自我标识,并将它保存在参数块的IdNum字中。
下面的代码是根据TesSeRact库的Int 2Fh处理程序编辑而成的,它显示出了处理程
序必须做哪些事情才能证明两个程序是完全相同的:
overparms:
cmp ax,5453h ;ax=5453h for TesSeRact
jne not_our_2F ; some other multiplex function
push dS ; Save for next handler
push CS
pop ds ; set DS while here
push ax
push bx
or bx, bx ; do check for install first,
jnz test_for_1 ;tny other function test
;following is the CHECK INSTALL code
;DS:SI points to ID string
;CX iS current number in chain
push CX
push Si ; Save SI for next one
lea di,UserParms ;the program copy of IDStr
push CS
pop es
mov cx,8 ;test for match
rep cmpsb
pop Si
pop cx
jnz next_one ;no match, not us
pop bx ;matched, empty stack
pop ax
mov cX,es:[di] ;return IdNum in cx
xor ax,ax
dec ax ;AX=-1 means already her
jmp shor done_2F
next_one ; try next higher ID code :
Inc CX
pop bx ;restore for next to use
pop ax
pop ds
not_our_2f: ;chain to next 2F handler
jmp dword ptr[oldint2F] ; via saved pointer to it
done_2F: ; return tO caller
pop ds
iret
C.3功能01h(返回用户参数指针)
若要支持TesSeRact标准,至少还得需要的一种功能便是功能01h,它必须返回一个
指向用户参数块区域的远指针。该功能的调用方法如下:
mov ax, 5453h
mov bX,01h ; function number
mov cx,TsrIdNum ; identmcation number
int 2Fh
如果CX中的标识号与TSR的ID号(由功能00h返回的)相符合,则该功能在返回
时必须让ES:指向用户参数(UserParms)区,并让AX等于0。下面的代码段列举了这样
做的一种方法:
cest_for_1:
cmp cx,IdNum ;if not Function 00h
jne not_our_2F ;the program copy
push cs ;got it, set up for return
pop es
lea bx,UserParms
xor ax, ax ;success status code
pop ds
jmp done_2F
C.4其它TesSeRact功能
完整的TesSeRact文档对其它TesSeRact功能进行详细的介绍,这种文档可从
TesSeRact开发队伍中获取或通过从BBS中卸载下来,以及可从专用于TesSeRact库的
联机服务中获得。如果希望得到一份TesSeRact的Int 2Fh处理程序的源代码,用户可按
下面的地址寄上一封信,并在信封上注明自己的地址:
TesSeRact Development Team
1657 The Fairwavs, Suite 101
Jenkintown,PA 19046
若想了解更为详细的信息,读者可按照CompuServe 7073120或MCIMAIL 315-5415
(TESSERACT)这两个地址与TesSeRact Development Team取得联系。
对于在同一时间里同时使用几种TSR程序来说,长期以来一直存在着一个问题,这
就是:当这些程序之间出现冲突时,我们找不到任何可遵循的标准来管理冲突。
早在1986年,一大群TSR开发者组织起了一支队伍,旨在建立这样一种标准。大多
数在TSR开发上居于领导地位的开发者参加了这一组织。
然而,在经过首次努力尝试以生产出一种可供独家程序和商业化程序使用的完整应
用程序接口(这种努力未能得到商用TSR出版部门的足够支持)之后的一段时间时,许多
成员离开了这一队伍,并转而从事其它方面的研究工作。不过,他们在共同研究期间已开
发并发行了一种接口,该接口允许开发者与他们自己的(或其它人的)TSR进行通信,此
外,他们的设计部门还把用于Microsoft和Turbo C、TurboPascal版本4和版本5以及汇
编语言程序的原有例程库(即众所周知的TesSeRact)设计成了一种可用的共享件。
TesSeRact标准指定了一组链接着DOS的多路复用中断(2Fh)的功能。由于DOs使
用这种中断来与其自己的TSR(如ASSIGN、PRINT和SHARE)通信,因此,TesSeRact
开发队伍感到最合适的方法是用相同的接口来服务于不同的TSR程序。并且通过把AX
设置为某个特殊代码(5453h或ASCII中的TS)来调用中断2Fh便可访问这些TesSeRact
功能。
但这种用法与已公开的Int 2Fh标准用法不相符,在采用标准用法时,DOS规定:标
识代码必须在AH寄存器中(并在80h-FFh范围内),AL=0表示该中断用于已“安装
否?”的功能。
在公开TesSeRact的正式用法之前,这支开发队伍已开发出了TesSeRact的标准,并
且初始拷贝的用途太广泛了,以致不允许对这样一种基本特征作出改变。不相容性也不会
造成任何问题,因为目前尚不知道哪个功能当前正使用54h代码(即使有程序在使用,那
么它还同时拥有53h功能的机会几乎没有)。
还值得一提的是,自从版本3.3引入了APPEND之后,DOS就开始不遵循它自己的
规则;它使用了B7h代码,而这个代码的正式身份是作为非DOS应用程序的保留代码。
为了实现减少不同来源的TSR之间彼此产生的冲突这一原始目标,这支开发队伍还
鼓励所有开发者在各自的代码中支持TesSeRact标准。具体做法是通过开发一个用于Int
2Fh的处理程序,以便支持用户参数块和本附录将通过特殊的TS标识代码来介绍的两
种功能。
C.1用户参数块
与TesSeRact兼容的要求之一是必须支持UserParms数据区。该区域的描述如下(这
一区域必须处在用于Int 2Fh的TSR处理程序的开头):
New_2F: Jmp 0verParms ; Int 2F vector points here
UserParms db 8 dup l(' ') ; 8-byte Program ID string
IdNum dw 0 ; TSR identification number
FuncFlag dd 0ffffffffh ; supported function bit map
HotKey db 0 ; scan code of hot key to use
ShiftSt db 0 ; shift state to use for popup
HotFlag db 0 ;which hot key iS in use
ExtCnt db0 ; number of extmhot keys
ExtHot dd 0 ; pointer to extra hot keys
Status dw 0 ; TSR Status flags
OurPSP dw 0 ; ourPSP segment
ourDTA dd 0 ; our DTA region
DSeg dw 0 ; user's default data Segment
注意,这里仅仅只是列举该数据区结构的一部分;而没有列举由TesSeRact库保持并
使用的元素。
FuncFlag是一个位映象的4字节变量,显示着TSR所支持的所有多路复用功能。每
当调用这种功能时,必须通过BX把其功能号传送给处理程序,而不是像标准情况下通过
AL来传送,其原因我们曾解释过。该变量的映象如下:
位 0 功能00h(检查安装—必需功能)
位1 功能01h(返回用户参数—必需功能)
位2 功能02h(检查热键)
位3 功能03h(置换INT24h)
位4 功能04N(返回数据指针)
位5 功能05h(设置附加热键)
位6-7 未定义—留待将来使用
位8 功能10h(允许TSR)
位9 功能11h(禁止TSR)
位10 功能12h(从RAM中释放TSR)
位11 功能13h(重新启动TSR)
位12 功能14h(获取当前状态)
位13 功能15h(设置TSR状态)
位14 功能16h(获取弹出式打印)
位15 未定义 —留待将来使用
位16 功能20h(调用用户进程)
位17 功能21h(填充键盘缓冲区)
位18- 31 未定义—留待将来使用
如果TSR支持所用的功能,那么必须把对应的位置为1,否则必须将其置为0,使用
TesSeRact库例库的程序在返回时会把FuneFlag置为FFFFFFFFh。其它的TSR则必须
把未定义的变量设置为0,以便同它们自己的变量区别开来。
C.2功能00h(检查安装)
检查安装(功能00h)可确定系统是否安装了某个程序。该功能可通过以下方式来调
用:
mov ax , 5453h ; TS code
mov si , offset IDStr ; see below
mov ds,seg IDStr
xor cx ,cx ; handle counter
xor bx,bX ; function 0000
int 2Fh
IDStr是一个8字节数据区,它保存着一个独一无二的TSR标识符串。 Int 2Fh例程
必须把传送给它的字符串(如下例所示)与它自己的8字节字符串进行比较。如果这两个
字符串相符合,TSR在返回时就必须把CX设置为它自己的TSR句柄,并把AX寄存器
设置为0FFFFFh。
如果标识字符串与传送的字符串不匹配,那么TSR应恢复所有寄存器,增加一个cx
寄存器,并继续沿着程序链往下传送中断。在使用该功能时如果在链接到下一个TSR之
前,系统中每个TesSeRact兼容的TSR都增加了一个CX寄存器,而在此时,中断进程又
实际上返回到调用者这边,那么在这种时候,CX寄存器要么为被找到的TSR的句柄,或
者在没有找到与IDStr相匹配的TSR时为下一个可用的句柄。
如果没有能找到匹配,在返回时AL就不会等于FFh;这样,TSR安装程序就可把
CX的内容用作句柄,以通过它来进行自我标识,并将它保存在参数块的IdNum字中。
下面的代码是根据TesSeRact库的Int 2Fh处理程序编辑而成的,它显示出了处理程
序必须做哪些事情才能证明两个程序是完全相同的:
overparms:
cmp ax,5453h ;ax=5453h for TesSeRact
jne not_our_2F ; some other multiplex function
push dS ; Save for next handler
push CS
pop ds ; set DS while here
push ax
push bx
or bx, bx ; do check for install first,
jnz test_for_1 ;tny other function test
;following is the CHECK INSTALL code
;DS:SI points to ID string
;CX iS current number in chain
push CX
push Si ; Save SI for next one
lea di,UserParms ;the program copy of IDStr
push CS
pop es
mov cx,8 ;test for match
rep cmpsb
pop Si
pop cx
jnz next_one ;no match, not us
pop bx ;matched, empty stack
pop ax
mov cX,es:[di] ;return IdNum in cx
xor ax,ax
dec ax ;AX=-1 means already her
jmp shor done_2F
next_one ; try next higher ID code :
Inc CX
pop bx ;restore for next to use
pop ax
pop ds
not_our_2f: ;chain to next 2F handler
jmp dword ptr[oldint2F] ; via saved pointer to it
done_2F: ; return tO caller
pop ds
iret
C.3功能01h(返回用户参数指针)
若要支持TesSeRact标准,至少还得需要的一种功能便是功能01h,它必须返回一个
指向用户参数块区域的远指针。该功能的调用方法如下:
mov ax, 5453h
mov bX,01h ; function number
mov cx,TsrIdNum ; identmcation number
int 2Fh
如果CX中的标识号与TSR的ID号(由功能00h返回的)相符合,则该功能在返回
时必须让ES:指向用户参数(UserParms)区,并让AX等于0。下面的代码段列举了这样
做的一种方法:
cest_for_1:
cmp cx,IdNum ;if not Function 00h
jne not_our_2F ;the program copy
push cs ;got it, set up for return
pop es
lea bx,UserParms
xor ax, ax ;success status code
pop ds
jmp done_2F
C.4其它TesSeRact功能
完整的TesSeRact文档对其它TesSeRact功能进行详细的介绍,这种文档可从
TesSeRact开发队伍中获取或通过从BBS中卸载下来,以及可从专用于TesSeRact库的
联机服务中获得。如果希望得到一份TesSeRact的Int 2Fh处理程序的源代码,用户可按
下面的地址寄上一封信,并在信封上注明自己的地址:
TesSeRact Development Team
1657 The Fairwavs, Suite 101
Jenkintown,PA 19046
若想了解更为详细的信息,读者可按照CompuServe 7073120或MCIMAIL 315-5415
(TESSERACT)这两个地址与TesSeRact Development Team取得联系。