关于 TSR 的小问题

发布于 2022-06-10 11:51:45 字数 1084 浏览 366 评论 10

我最近照着书上写了一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

紫罗兰の梦幻 2022-06-14 04:22:46

你的程序好像有错误,找出几个,但是还是不好用.
比如:你的程序未驻留退出,即然未驻留退出如何称为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

轻拂→两袖风尘 2022-06-14 04:22:43

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的程序。。。
有问题在提吧,,,,

-梦年海沫深 2022-06-14 04:22:42

能不能详细点啊???

我还是不懂啊!!

不过还是要谢谢你们啦!
yuqiang0304@163.net

雨巷深深 2022-06-14 04:22:37

什么地方不懂啊?

热血少△年 2022-06-14 04:22:31

我想我的那个程序里注释得已经蛮清楚啦.
你再照着书看看就明白啦.

我的程序中真正的TSR部份很少,反而显示字符串部分占了较大的比例

今晚就要回去啦,只能到下周五晚再给你回复啦.

虐人心 2022-06-14 04:14:49

看了楼顶那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我!:)

星星的轨迹 2022-06-14 04:01:46

好!
我试一下!!!
可以留下e-mail吗?
大家交个朋在!
yuqiang0304@163.net

℡Ms空城旧梦 2022-06-14 03:55:53

cner@8848.net
不知道什么时候会去看我的信箱。。。。:)

风渺 2022-06-14 03:42:45

还有~~ 你这个ASM是com格式,int27也只能在com上使用! 然后如果只是编译为exe格式
也同样会死机!
d.boy@126.com

红尘作伴 2022-06-13 04:10:04

修正错误如下。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文