控制事物顺序的最简单方法是根据它们需要在最终程序中的位置将所有内容放入段中,然后使用您首先链接的“模板”程序集文件来对段进行排序。默认情况下,链接器按照遇到的顺序对段进行排序,因此,如果程序中使用的所有段都位于第一个文件中,那么该文件将确定段的顺序。
TSR应该是一个单段COM文件这一事实使事情变得复杂,但仍然可以使用多个汇编程序段。汇编程序段不必与程序使用的段一一对应。在这种情况下,您只需要使用汇编程序段将事情分组在一起。
例如,您可以使用如下模板文件:
EXTERN init_start:NEAR
PUBLIC resident_end
PSPSEG GROUP RTEXT, REND, ITEXT
RTEXT SEGMENT PUBLIC PARA 'RESIDENT'
ORG 100h
start:
jmp init_start
RTEXT ENDS
REND SEGMENT PUBLIC BYTE 'REND'
resident_end:
REND ENDS
ITEXT SEGMENT PUBLIC BYTE 'INIT'
ITEXT ENDS
END start
如果您在
RTEXT
节和中的初始化代码
ITEXT
然后,前一段代码将放在程序的开头,后一段代码放在末尾。符号
resident_end
将位于中间,将程序退出后需要保留在内存中的代码与未退出的代码分开。
的目的
GROUP
指令是通知汇编程序和链接器
RTEXT文本
,
REND
和
ITEXT文本
都应该是一个实际的片段。这一点很重要,因为他们需要知道使用的任何地址都应该与组相关
PSPSEG
,程序使用的实际段。请注意
“组”
指令创建的别名实际上对链接程序中的顺序没有任何影响。
因为COM程序总是从程序的开头开始执行,所以我将代码放在这个模板中,跳转到最后的初始化代码。如果你正在创建一个EXE,你就不需要这个,你可以离开
RTEXT文本
空的,只使用
END
而不是
END start
. 具有入口点的文件将使用
结束
而是使用入口点的标签。
以下是一个最小TSR,旨在与上述模板链接:
EXTERN resident_end:NEAR
PUBLIC init_start
PSPSEG GROUP RTEXT, ITEXT
RTEXT SEGMENT PUBLIC PARA 'RESIDENT'
ASSUME DS:NOTHING, SS:NOTHING, CS:PSPSEG
old_handler DD 0cccccccch
interrupt_handler:
jmp [old_handler]
RTEXT ENDS
ITEXT SEGMENT PUBLIC BYTE 'INIT'
ASSUME DS:PSPSEG, SS:PSPSEG, CS:PSPSEG
init_start:
mov ax, 3508h
int 21h ; get old timer interrupt handler
mov WORD PTR [old_handler], bx
mov WORD PTR [old_handler + 1], es
mov dx, OFFSET interrupt_handler
mov ax, 2508
int 21h ; set new timer interrupt handler
mov ax, 3100h
mov dx, OFFSET resident_end + 15
shr dx, 4
int 21h ; terminate and stay resident
ITEXT ENDS
END
有必要重复
“组”
指令,但您只需列出文件中使用的段。这段代码是用现代版本的MASM编写和测试的(仅限于链接),如果您使用的是TASM,可能需要显式地告诉汇编程序相对于
PSPSEG
每次使用
OFFSET
. 例如
mov dx, OFFSET PSPSEG:interrupt_handler
.