首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 操作系统 > Linux > TSR驻留程序
【标  题】:TSR驻留程序
【关键字】:TSR
【来  源】:http://blog.chinaunix.net/article.php?articleId=10668&blogId=3771

TSR驻留程序

这是一个完整的TSR例程,读者可把自己的的应用程序添加在实例程序中相应的地方。但有两点需要注意:
1。在TSR程序内部,不要使用动态内存分配函数,因为该类函数从堆中分配内存,而堆在初始化时作为未驻留的空间被释放掉。如需内存分配,最好在TSR初始化时分配好,之后再保留内存块的指针。
2。不要在TSR程序内部使用exit()函数,以防非正常退出。

/***********************************************************************************
以下是一个完整的TSR例程,读者可把自己的的应用程序添加在实例程序中相应的地方。但有两点需要注意:
1。在TSR程序内部,不要使用动态内存分配函数,因为该类函数从堆中分配内存,而堆在初始化时作为未驻留的空间被释放掉。如

需内存分配,最好在TSR初始化时分配好,之后再保留内存块的指针。
2。不要在TSR程序内部使用exit()函数,以防非正常退出。
完整的实例程序如下:
***********************************************************************************/
/*TSR驻留程序设计框架*/
#include
#include
#include
#include
#include
#include
#include

/*一些数据的定义*/
#define STACK_SIZE 8192  /*栈的大小*/
#define KEYBOARD 0x60 /*键盘数据端口*/
#define PSP_TERMINATE 0x0a /*PSP中的结束地址*/
#define PSP_PARENTPSP 0x16 /*PSP中的父进程的PSP*/
#define PSP_ENVIRON 0x2C /*PSP中的环境块的地址*/
#define SCANCODE 52    /*字符.的键码*/
#define ALTKEY 8       /*ALT键的代码,用ALT+.的组合键来激活此TSR程序*/
#define PARAGRAPHS(x) ((FP_OFF(x)+15)>>4)
/*变量的定义*/
char far *indos_ptr=0; /*指向DOS安全标志的指针*/
char far *crit_err_ptr=0; /*指向致命错误标志的指针*/
char far *stack_ptr; /*TSR栈的指针*/
char far *dta1;  /*前台进程的磁盘传输区地址*/
char far *dta2;
unsigned ss_save; /*用于保存堆栈段寄存器*/
unsigned sp_save; /*用于保存堆栈指针寄存器*/
static int active=0; /*TSR激活标志*/
static int popup_dosBusy=0; /*该标志为1,表明DOS繁忙时热键被按*/
static int int28_active=0; /*该标志为1,表明INT28处于活动状态*/
static int int13_active=0; /*该标志为1,表明INT13处于活动状态*/
static unsigned foreground_psp; /*前台进程的PSP*/
static unsigned long terminateAddr; /*删除TSR时使用*/
static int key; /*读键盘端口时使用*/
extern int sign; /*删除TSR程序时,汇编子程序使用的返回标志*/
static union REGS r;
static struct SREGS s;
static struct DOSERROR dosErr;
typedef struct
{
    unsigned bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags;
}INTERRUPT_REGS;
/*保存原中断的函数指针*/
void interrupt (*old_int8)(void); /*时钟中断*/
void interrupt (*old_int9)(void); /*键盘中断*/
void interrupt (*old_int1B)(void); /*CTRL+BREAK中断*/
void interrupt (*old_int23)(void); /*CTRL+C中断*/
void interrupt (*old_int24)(void); /*严重错误中断*/
void interrupt (*old_int28)(void); /*DOS空闲中断*/
void interrupt (*old_int62)(void); /*通讯中断*/
void interrupt (*old_int13)(void); /*磁盘读写中断*/
/*函数原型声明*/
void interrupt far new_int8(void);
void interrupt far new_int9(void);
void interrupt far new_int1B(void);
void interrupt far new_int23(void);
void interrupt far new_int24(INTERRUPT_REGS p);
void interrupt far new_int28(void);
void interrupt far communicate(INTERRUPT_REGS p);
void interrupt far new_int13(INTERRUPT_REGS p);
void help_message(void);
int dosBusy(void); /*如果DOS繁忙,该函数返回非零值*/
int int28DosBusy(void); /*如果DOS安全标志为1,并且致命错误标志非零,该函数返回非零值*/
void initIndos(void); /*初始化DOS安全标志的指针*/
void tsr_active(void); /*TSR激活函数*/
void tsr_exit(void); /*TSR退出函数*/
void do_deinstall(char *program); /*判断TSR是否删除的函数*/
void set_stack(void); /*保存栈*/
void restore_stack(void); /*恢复栈*/
void setpsp(unsigned segpsp); /*设置PSP*/
void setExtErr(struct DOSERROR near * err); /*设置扩展错误信息*/
int deinstall(void); /*删除TSR函数,该函数用汇编子程序编写*/
/*绝对恢复原中断的函数*/
int unLinkVect(int vect,void interrupt (*newint)(),
        void interrupt (*oldint)());
/*主函数*/
void main(int argc,char *argv[])
{
    union REGS regs1,regs2;
    struct SREGS sregs;
    unsigned memory; /*驻留内存大小的变量*/
    unsigned far *fp; /*指向环境块段址的指针*/
    initIndos(); /*初始化DOS安全标志和致命错误标志*/
    switch(argc)
    {
 case 1:
     if(getvect(0x61)!=NULL)
     {
  puts("TSR program already installed!n");
  system("PAUSE");
  exit(1);
     }
     break;
 case 2:
     if(toupper(argv[1][0])=='D' && (getvect(0x62)!=NULL))
  do_deinstall(argv[0]);
     else help_message();
     break;
 default:
     help_message();
    }
    /*设置TSR自己的栈*/
    stack_ptr=malloc(STACK_SIZE);
    if(stack_ptr==NULL)
    {
 printf("Not enough memory!n");
 system("PAUSE");
 exit(1);
    }
    stack_ptr+=STACK_SIZE;
    /*保留中断向量*/
    old_int8=getvect(0x08);
    old_int9=getvect(0x09);
    old_int13=getvect(0x13);
    old_int28=getvect(0x28);
    old_int62=getvect(0x62);
    /*设置中断向量*/
    setvect(0x08,new_int8);
    setvect(0x09,new_int9);
    setvect(0x13,new_int13);
    setvect(0x28,new_int28);
    setvect(0x62,communicate);
    /*释放掉环境块*/
    fp=MK_FP(_psp,PSP_ENVIRON);
    freemem(*fp);
    /*计算驻留空间,并释放掉多余的堆空间*/
    segread(&sregs); /*读取段寄存器*/
    memory=sregs.ds+PARAGRAPHS(stack_ptr)-_psp;
    setblock(_psp,memory); /*调整内存空间*/
    keep(0,memory); /*驻留*/
}
/*主函数结束*/
/*捕获INT08时钟中断*/
void interrupt far new_int8()
{
    (*old_int8)(); /*连接原中断*/
    /*判断TSR能否弹出*/
    if(!active && popup_dosBusy && !dosBusy() && !int13_active)
    {
 popup_dosBusy=0;
 active=1;
 enable();
 tsr_active();
 active=0;
    }
}
/*捕获INT09键盘中断*/
void interrupt far new_int9()
{
    if(!active)
    {
 if(inportb(0x60)==SCANCODE) /*从端口读取扫描码*/
 {
     if((bioskey(2)&ALTKEY)==ALTKEY) /*读取移位状态*/
     {
  /*清键盘缓冲区*/
  key=inportb(0x61);
  outportb(0x61,key);
  outportb(0x20,0x20); /*告诉系统键盘中断结束*/
  if(!int13_active) /*如果没有磁盘读写,可以弹出TSR程序*/
  {
      popup_dosBusy=0;
      active=1;
      old_int9();
      tsr_active();
      active=0;
  }
  else
  {
      popup_dosBusy=1;
      (*old_int9)();
  }
     }
     else
  (*old_int9)();
 }
 else
     (*old_int9)();
    }
    else
 (*old_int9)();
}
/*捕获INT13磁盘读写中断*/
void interrupt far new_int13(INTERRUPT_REGS p)
{
    int13_active++;
    (*old_int13)();
    p.ax=_AX;
    p.cx=_CX;
    p.dx=_DX;
    p.flags=_FLAGS;
    --int13_active;
}
/*捕获INT1B CTRL+BREAK中断*/
void interrupt far new_int1B()
{
    /*Do Nothing*/
}
/*捕获INT23 CTRL+C中断*/
void interrupt far new_int23()
{
    /*Do Nothing*/
}
/*捕获INT24严重错误中断*/
void interrupt far new_int24(INTERRUPT_REGS p)
{
    p.ax=0x03; /*告诉DOS忽略该错误*/
}
/*捕获INT28 DOS空闲中断*/
void interrupt far new_int28()
{
    int28_active++;
    /*判断TSR能否弹出*/
    if(popup_dosBusy && (!int28DosBusy()) && !active && !int13_active)
    {
 active=1;
 tsr_active();
 active=0;
    }
    int28_active--;
    (*old_int28)();
}
/*通讯中断函数*/
void interrupt far communicate(INTERRUPT_REGS p)
{
    terminateAddr=((long)p.bx<<16)+p.dx;
    if(!active)
    {
 enable();
 tsr_exit(); /*退出驻留程序*/
 active=1;
    }
}
void help_message(void) /*帮助信息*/
{
    printf("The correct way of using this TSR program is:n");
    printf("TSR[d]n");
    printf("TSR d stands for deinstalling the TSR program.n");
    printf("TSR stands for installing the program.n");
    system("PAUSE");
    exit(1);
}
void tsr_active(void) /*TSR激活函数*/
{
    set_stack(); /*设置自己的栈*/
    if(dosBusy() && !int28_active)
 popup_dosBusy=1; /*设置标志以便下一次INT08,INT28激活TSR*/
    else
    {
 popup_dosBusy=0;
 /*保存INT1B,INT23,INT24中断*/
 old_int1B=getvect(0x1B);
 old_int23=getvect(0x23);
 old_int24=getvect(0x24);
 /*设置新的INT1B,INT23,INT24中断*/
 setvect(0x1B,new_int1B);
 setvect(0x23,new_int23);
 setvect(0x24,new_int24);
 /*PSP切换*/
 foreground_psp=getpsp();
 setpsp(_psp);
 /*DTA切换*/
 dta1=getdta();
 dta2=MK_FP(_psp,0x80);
 setdta(dta2);
 /*保存前台进程的扩展错误信息*/
 dosexterr(&dosErr);
 /*清除键盘缓冲区*/
 /*此处设置你的TSR应用程序*/
 /*下面是一个极简单的示例,仅显示几个字符*/
 printf("TSR program has been installed!n");
 sound(532);
        delay(100);
        nosound();
 /*恢复前台进程的扩展错误信息*/
 setExtErr((struct DOSERROR near *)&dosErr);
 /*恢复前台进程的DTA*/
 setdta(dta1);
 /*恢复前台进程的PSP*/
 setpsp(foreground_psp);
 /*恢复INT1B,INT23,INT24中断*/
 setvect(0x1B,old_int1B);
 setvect(0x23,old_int23);
 setvect(0x24,old_int24);
    }
    restore_stack(); /*恢复栈*/
}
/*设置PSP的函数*/
void setpsp(unsigned segpsp)
{
    union REGS regs;
    if(!crit_err_ptr)
 return;
    *crit_err_ptr=0xff;
    regs.h.ah=0x50; /*0x50号中断函数用于设置PSP*/
    regs.x.bx=segpsp;
    intdos(®s,®s);
    *crit_err_ptr=0;
}
/*设置扩展错误信息函数*/
void setExtErr(struct DOSERROR near *err)
{
    r.x.ax=0x5D0A;
    r.x.bx=0x00;
    segread(&s);
    r.x.dx=(int)err;
    intdosx(&r,&r,&s);
}
void initIndos(void)
{
    union REGS regs;
    struct SREGS sregs;
    regs.h.ah=0x34;
    intdosx(®s,®s,&sregs);
    indos_ptr=MK_FP(sregs.es,regs.x.bx);
    regs.x.ax=0x5D06;
    intdosx(®s,®s,&sregs);
    crit_err_ptr=MK_FP(sregs.ds,regs.x.si);
}
/*判断DOS是否繁忙*/
int dosBusy(void)
{
    if(indos_ptr && crit_err_ptr)
 return (*crit_err_ptr || *indos_ptr);
    else
 return 0xFFFF;
}
int int28DosBusy(void)
{
    if(indos_ptr && crit_err_ptr)
 return (*crit_err_ptr || (*indos_ptr>1));
    else
 return 0xFFFF;
}
int unLinkVect(int vect,void interrupt (*newint)(),
        void interrupt (*oldint)())
{
    if(newint==getvect(vect))
    {
 setvect(vect,oldint);
 return 0;
    }
    return 1;
}
void tsr_exit(void)
{
    set_stack(); /*设置自己的栈空间*/
    if(!(unLinkVect(8,new_int8,old_int8) | unLinkVect(9,new_int9,old_int9) |
 unLinkVect(0x28,new_int28,old_int28) | unLinkVect(0x13,new_int13,old_int13) |
 unLinkVect(0x62,communicate,old_int62)))
    {
 /*把当前活动进程的PSP设置为TSR进程PSP中的父本PSP*/
 *(int far *)(((long)_psp<<16)+PSP_PARENTPSP)=getpsp();
 /*设置TSR进程PSP中的结束地址*/
 *(long far *)(((long)_psp<<16)+PSP_TERMINATE)=terminateAddr;
 /*设置TSR进程的PSP为当前活动进程的PSP*/
 setpsp(_psp);
 /*结束程序,退出到父本程序*/
 bdos(0x4C,0,0);
    }
}
void do_deinstall(char *program)
{
    fputs(program,stdout);
    deinstall();
    switch(sign) /*判断汇编子程序的返回标志*/
    {
 case 1:
     puts("Deactivated but not removed!n");
     break;
 case 2:
     puts("Deinstalled!n");
     break;
 default:
     puts("Unexpected errors!n");
     break;
    }
    system("PAUSE");
    exit(0);
}

/*******************C程序调用的两个汇编语言程序*****************************/
/**************************************************************************
_TEXT SEGMENT BYTE PUBLIC 'CODE' ;正文段
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA' ;段描述
_DATA ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
DGROUP GROUP _DATA,CONST,_BSS ;组描述
    ASSUME CS:_TEXT,DS:DGROUP,SS:DGROUP
_DATA SEGMENT
    PUBLIC _SIGN
    _SIGN DW 0 ;返回到C程序中的标志变量
_DATA ENDS
    PUBLIC _deinstall
    EXTRN _ss_save:NEAR
    EXTRN _sp_save:NEAR
_TEXT SEGMENT
_deinstall PROC FAR
    PUSH SI
    PUSH DI
    PUSH BP
    MOV WORD PTR  _ss_save,SS ;保存主程序的栈
    MOV WORD PTR  _sp_save,SP
    MOV CS:_ds_save,DS ;保存数据段
    MOV BX,CS
    MOV DX,OFFSET terminateAddr ;BX:DX指向程序的结束地址
    INC _sign
    INT 62H ;调用Communicate
    JMP SHORT noterminate
terminateAddr:
    MOV AX,CS:_ds_save
    MOV DS,AX
    INC _sign
    MOV SS,WORD PTR  _ss_save ;恢复栈
    MOV SP,WORD PTR  _sp_save
noterminate:
    POP BP
    POP DI
    POP SI
    RET
_deinstall ENDP
_ds_save DW 0
_TEXT ENDS
END

_TEXT SEGMENT BYTE PUBLIC 'CODE' ;正文段
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA' ;段描述
_DATA ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
DGROUP GROUP _DATA,CONST,_BSS ;组描述
    ASSUME CS:_TEXT,DS:DGROUP,SS:DGROUP
    PUBLIC _set_stack
    PUBLIC _restore_stack
    EXTRN _ss_save:NEAR
    EXTRN _sp_save:NEAR
    EXTRN _stack_ptr:NEAR
_TEXT SEGMENT
_set_stack PROC FAR
    POP AX ;保存返回值的偏移地址
    POP BX ;保存返回值的段地址
    MOV WORD PTR  _ss_save,SS ;保存前台程序的栈
    MOV WORD PTR  _sp_save,SP
    MOV SS,WORD PTR  _stack_ptr+2 ;设置TSR程序的栈
    MOV SP,WORD PTR  _stack_ptr
    PUSH BX ;正常返回
    PUSH AX
    RET
_set_stack ENDP
_restore_stack PROC FAR
    POP CX ;保存返回值的偏移地址
    POP BX ;保存返回值的段地址
    MOV WORD PTR  _stack_ptr+2,SS ;保存TSR程序的栈
    MOV WORD PTR  _stack_ptr,SP
    MOV SS,WORD PTR  _ss_save ;恢复前台进程的栈
    MOV SP,WORD PTR  _sp_save
    PUSH BX ;正常返回
    PUSH CX
    RET
_restore_stack ENDP
_TEXT ENDS
END
**************************************************************************/

php5安装笔记:【上一篇】
串行通信与重叠(异步)I/O:【下一篇】
【相关文章】
没有相关文章
【随机文章】
  • ORACLE常见错误代码的分析与解决(三)
  • 今日所读新闻
  • 单元测试究竟是测试什么?
  • 人工神经网络与模拟进化计算
  • Illustrator 8.0 入门基础教程(8)
  • 两个表格[Table]可以左右排放吗
  • TERMIOS详解
  • 请教网络高手 非常值得讨论的 问题
  • net start 可以启动的命令一览
  • 鼠标点击响应事件
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.