关于 TSR 的小问题
我最近照着书上写了一个 TSR 程序,可是不知道为什么就是不对!!!
这个程序是用来拦截 16h 中断的,可是一旦运行就像死机一样,键盘没法输入了,只好
重起,请各位高手帮我看一下!!!!
还有,我的书一是用了一个 oldint dd ?,然后把 16h 中断的地址保荐在里面,后面用了
jmp word ptr oldint,可是我编译时老是出错,告诉我好像是 oldint 这个符号在程序
里没有找到,怎么都不行啊!!
怎么办啊???
yuqiang0304@163.net
cseg segment
assume cs:cseg,ds:cseg
oldint dw ?
dw ?
temp db ?
org 100h
start:
jmp change
newint proc far
assume cs:cseg
assume ds:nothing
sti
pushf
mov temp ,ah
call dword ptr oldint
cmp temp,0
jnz return
;call dword ptr oldint
cmp al,'Y'
jnz next
mov al,'y'
jmp return
next: cmp al,'y'
jnz return
mov al,'Y'
return: popf
iret
newint endp
change:
assume cs:cseg,ds:cseg
mov bx,cs
mov ds,bx
mov al,16h
mov ah,35h
int 21h
mov oldint,bx
mov oldint[2],es
mov al,16h
mov ah,25h
mov dx,offset newint
int 21h
mov dx,offset change
int 27h
cseg ends
end start
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
你的程序好像有错误,找出几个,但是还是不好用.
比如:你的程序未驻留退出,即然未驻留退出如何称为TSR程序?
以下是我以前做的一个小的TSR程序,请看:
-------------------------------------------------------
;=========================================< 彬 >==
;名 称:
;用 途:在内存中驻留,以屏幕的左上方交替出现预设的
; 的字符串
;语 言:
;日 期:
;=================================================
CSEG SEGMENT
ASSUME CS:CSEG,DS:CSEG
SrcInt dd 0
Count dw 18
Cursor dw 0
TabStrA db 'WelCome To My HomePage'
StrLen = $-offset TabStrA
TabStrB db '-=Http://vbin.51.net=-'
TabFlag db 0
NowInt:
cmp cs:Count,0
jz Next
dec cs:Count
jmp dword ptr cs:SrcInt
Next:
mov ax,18
mov cs:count,ax
sti
push ds
push es
push ax
push bx
push cx
push dx
push si
push bp
push cs
pop ds
push ds
pop es
;保存当前光标位置
;DH中存的是行号,DL是列号
mov bh,0
mov ah,3
int 10h
mov Cursor,dx
mov al,0 ;写模式 0表示移动光标(想要光标不显示可设置功能1)
mov ah,13h ;写字符串
mov bh,0 ;当前页号
mov dh,0 ;行
mov dl,0 ;列
mov cx,StrLen ;字符数
cmp cs:TabFlag,0
jnz TypeB
mov bl,0eh ;写属性 黑底黄字
mov bp,offset TabStrA ; 设要打的字符串
mov cs:TabFlag,1
jmp Goon
TypeB:
mov bl,0fh ;写属性 黑底亮白字
mov bp,offset TabStrB ; 设要打的字符串
mov cs:TabFlag,0
Goon:
int 10h
;置光标位置
mov bh,0
mov dx,Cursor
mov ah,2
int 10h
pop bp
pop si
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
iret
start:
mov ax,CSEG
mov ds,ax
mov es,ax
mov ax,351ch ; 取1C号中断的地址
int 21h
mov word ptr SrcInt,bx ; 保存偏移
mov word ptr SrcInt+2,es ; 保存段值
mov dx,offset NowInt ; 置新的中断
mov ax,251ch
int 21h
mov dx,offset start+15
mov cl,4 ; 计算驻留节数
shr dx,cl
add dx,10h ; 加上PSP的节数
mov al,0
mov ah,31h ; 驻留退出
int 21h
CSEG ends
end start
y616:
我在98下帮你编译、连接都没错
程序是你上面的程序。masm是5。0的。
不知道你的工具是不是也是一样的?
但是,我在98下试着运行,却引起98的死机,估计是我操作不当!
dos下,我还没看,
我看了看你的程序。
你的程序一开始就跳到:
change:
assume cs:cseg,ds:cseg
mov bx,cs
mov ds,bx
(打个岔,我一直以为cs不能送值给通用寄存器的,
没想到却通过了编译,哈哈,孤陋寡闻的我。!)
到下面,你通过这里驻留内存??
mov dx,offset change
int 27h
好象格式不对吧?开始地址和长度好象不对吧?
(手头没书,无法确定!)
顺便问一下,你int 27h执行了之后,,,
你的下一条指令是执行什么呢?
返回?返回哪里???
可能就是在这里死机的!!!
你可以参照一下vbin的程序。。。
有问题在提吧,,,,
能不能详细点啊???
我还是不懂啊!!
不过还是要谢谢你们啦!
yuqiang0304@163.net
什么地方不懂啊?
我想我的那个程序里注释得已经蛮清楚啦.
你再照着书看看就明白啦.
我的程序中真正的TSR部份很少,反而显示字符串部分占了较大的比例
今晚就要回去啦,只能到下周五晚再给你回复啦.
看了楼顶那ASM程序,我发现3个问题!
1。 在newint16中 mov temp ,ah 这个没有指定使用段,默认为ds段,但现在的ds并不是程序数据段 应当改为 mov cs:temp ,ah 和 cmp cs:temp,0
2. call dword ptr oldint 这里也是同样问题! 没有指定使用段,默认为ds段!
改call dword ptr cs:oldint
3. call dword ptr oldint 问题也出现在这指令! int X 的动作是 实际是两条指令
pushf 然后是 call dword ptr [xxxxxx] 而 iret 实际也是两条指令 popf 然后retf
所以newint16中只是简单的call dword ptr oldint,那在原来的 int 16中执行了iert
后,就把堆栈破坏!因为这个call 并没有和int 一样 pushf
修改就在call dword ptr cs:oldint 前加 pushf
上面的代码我只是看了一下,没仔细编译测试过,呵呵~~ 如有看错,看漏可别K我!:)
好!
我试一下!!!
可以留下e-mail吗?
大家交个朋在!
yuqiang0304@163.net
cner@8848.net
不知道什么时候会去看我的信箱。。。。:)
还有~~ 你这个ASM是com格式,int27也只能在com上使用! 然后如果只是编译为exe格式
也同样会死机!
d.boy@126.com
修正错误如下。
cseg segment
assume cs:cseg,ds:cseg
oldint dw ?
dw ?
temp db ?
org 100h
start:
jmp change
newint proc far
assume cs:cseg
assume ds:nothing
PUSHF ;;先 PUSHF
sti
;;pushf ;;不要此句
mov cs:temp ,ah ;;加 CS:
call dword ptr CS:oldint ;;加 CS:
PUSHF ;;保存原 INT 16H 的返回标记
cmp CS:temp,0
jnz return
;call dword ptr oldint
cmp al,'Y'
jnz next
mov al,'y' ;;大写 变 小写
jmp return
next: cmp al,'y'
jnz return
mov al,'Y' ;;小写 变 大写
return: popf ;;恢复原 INT 16H 返回的标记
;;iret ;;此处不能用
RETF 2 ;;必须用此命令
newint endp
change:
assume cs:cseg,ds:cseg
mov bx,cs
mov ds,bx
mov al,16h
mov ah,35h
int 21h
mov oldint,bx
mov oldint[2],es
mov al,16h
mov ah,25h
mov dx,offset newint
int 21h
mov dx,offset change
;;int 27h ;;建议换成以下调用
ADD DX,15
SHR DX,4
MOV AH,31H ;;请查资料确认,31H是驻留并退出
INT 21H
cseg ends
end start