我正在写一个简单的TSR程序,但是我收到了错误。
我试图通过Int 90H
执行它,但出于某种原因,它已经崩溃了。
我是TSR的新手,所以问题可能很简单。
TSR:
; Copy non-small letters
.model tiny
.code
ORG 100H
start:
push bp
push si
push cx
push bx
; save registers
mov bp, sp
sub sp, cx
sub sp, 1 ; for $
mov di, bp
mov si, bx
copy:
cmp [si], 'a'
jl bad
; not small letter
cmp [si], 'z'
jg bad
; not small leter
; good
mov ax, [si]
mov [bp], ax
dec bp
bad:
inc si
loop copy
mov [bp-1],'$'
mov ah, 09
mov dx, di
int 21H
install:
mov al, 90H
mov ah, 25H
mov dx, offset start
int 21H
finish:
pop bx
pop cx
pop si
pop bp
; ^ restore registers
mov ah, 31
int 21H
iret
; end
end start
主程序:
.model small
.stack 64
.data
string db "Hey There"
.code
start:
lea bx, string
mov cx, 09
int 90H
; end
mov ah, 4ch
int 21H
end start
你知道我的程序崩溃的原因吗?
答案 0 :(得分:0)
十多年前我为DOS编写了一个TSR调试器(类型),所以我可能忘记了一些东西。
无论如何,您的中断处理程序除了cs
指向中断处理程序的段并且ip
(显然)指向您的中断代码之外,您不能假设任何其他内容,这就是您所拥有的所有内容,以及您不能修改中断处理程序中的任何其他内容(除了您特别想要修改的内容)。你必须存储你使用的所有寄存器,但你不能只是push
它们到堆栈,因为你不能假设有任何堆栈。因此,请确保保留足够的内存来存储您在中断处理程序中修改的所有寄存器,并在保存寄存器时记得使用cs
作为段寄存器,而不是默认的ds
,也不是{{1} },es
,fs
或gs
,因为它们都可以指向内存中的任何位置,当然也不会指向保留给TSR的任何内存块。将旗帜存放在一个好主意中。
ss
个调用。您可以使用BIOS调用(int 21h
)或直接写入视频内存(但如果您在TSR中写入视频内存,请先检查视频模式)。无论如何,写入TSR中的视频内存可能会导致问题,因为您不知道当前运行的程序如何使用它。
如果你想确保在你自己的中断处理程序中没有执行其他中断,中断处理程序开头的int 10h
会阻止大多数中断,恕我直言是个好主意。请务必在cli
之前sti
允许中断。
答案 1 :(得分:0)
在我们使用iret指令从中断服务程序(ISR)返回之前,我们必须向“mov al,020h”+“out 20h,al”发送“中断结束”-signal(EOI)第一个可编程中断控制器(PIC 1; 8259A)。
另一种方法是跳远到旧的ISR,而不是发送EOI并与iret一起返回。
---------------
Ralf Browns x86 / MSDOS中断列表(RBIL)
http://www.pobox.com/~ralf
http://www.pobox.com/~ralf/files.html
ftp://ftp.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/
RBIL-> inter61d.zip-> PORTS.A
---------- P0020003F --------------------------
端口0020-003F - PIC 1 - 可编程中断控制器(8259A)
参见:PORT 00A0h-00AFh“PIC 2”,INT 08“IRQ0”,INT 0F“IRQ7”
....有关详细信息请查看RBIL ..
; ------------
要成为TSR,我们必须使用INT 27h来终止我们申请的ISR部分居住。
RBIL-> inter61c.zip-> INTERRUP.K
-------- d-27 ---------------------------------
INT 27 - DOS 1+ - 终止和留住居民
DX =保持驻留的字节数(最大FFF0h)
CS = PSP的分段
回报:永远不会
注意:这是一个过时的电话
从PSP中恢复INT 22,INT 23和INT 24
不会关闭任何打开的文件
对于将保持驻留的最小字节数是110h
用于DOS 3.0+的DOS 2.x和60h; DOS 1.x没有最低要求,其中
在COMMAND.COM而不是DOS内核中实现此服务
SeeAlso:INT 21 / AH = 31h
; ----------
它认为在我们的ISR中使用软件中断调用并不是一个好主意。
所以我更喜欢直接写入视频内存,例如在屏幕的上方角落写一些数字以显示当前时间。
------
用于设置和获取中断向量:
RBIL-> inter61b.zip-> INTERRUP.F
-------- d-2125 -------------------------------
INT 21 - DOS 1+ - 设置中断矢量
AH = 25h
AL =中断号码
DS:DX - >新的中断处理程序
注意:此功能优于直接修改中断
矢量表
一些DOS扩展器在这个函数上放置了一个API,因为它不是
在保护模式下直接有意义
在DR DOS 5.0-6.0下,此功能不使用任何
DOS内部堆栈,因此可以随时调用;然而,
在Novell DOS 7.0 - DR-DOS 7.02下,此功能不可重入
自1998/05/29起,DR-DOS 7.03不再使用任何内部堆栈和
更早地测试此功能,以允许最小的堆栈使用
除了IRET框架之外,只有两个单词,允许它为
从INT 21h函数调用,特别是设备驱动程序。这
修复MCS SMB客户端
Novell NetWare(新的DOS请求者除外)监视
的偏移量
任何INT 24设置,如果等于启动时的值,则替换为
它自己的处理程序,允许处理网络错误;这介绍了
INT 24处理程序偏移的任何程序的潜在错误
恰好与COMMAND.COM相同,它不会有INT 24
处理器安装
SeeAlso:AX = 2501h,AH = 35h
-------- d-2135 -------------------------------
INT 21 - DOS 2+ - 获取中断矢量
AH = 35h
AL =中断号码
返回:ES:BX - >当前中断处理程序
注意:在DR DOS 5.0+下,此功能不使用任何DOS内部
堆栈,因此可以随时调用
SeeAlso:AH = 25h,AX = 2503h
设置中断向量的另一种方法是写入向量本身的存储位置:
从标签“TIMER_INT”开始将Timerinterrupt(8)设置为新的ISR的示例:
mov ax,0
mov ds,ax
cli
mov WORD PTR ds:[8*4],OFFSET TIMER_INT
mov WORD PTR ds:[8*4+2],cs
sti
德克