我尝试编写自己的键盘中断处理程序(使用DOS),它只在屏幕上写入一条消息。当没有按下键盘时,会打印另一条没有结束的信息(因此无法正常停止程序,但这并不重要)。当MYTASK例程中的DOS中断行被注释时,中断处理程序运行良好,但由于它们被取消注释,我的程序崩溃("遇到非法指令")。我哪里可以犯错?
DOSSEG
.MODEL TINY
.STACK 100h
.DATA
TaskMessage DB 13,10,'Now task executed',13,10,'$'
IHandlerMessage DB 13,10,'Now interrupt handler executed',13,10,'$'
KEEP_CS DW 0
KEEP_IP DW 0
.CODE
mov ax,@Data
mov ds,ax
jmp beg
mytask proc far
infiloop:
;mov ah,09h
;mov dx,OFFSET TaskMessage ; program fails when these 3 lines
;int 21h ; are uncommented
cmp bx,bx
je infiloop
ret
mytask endp
beg:
mov AH,35h
mov AL,09h
int 21h
mov KEEP_CS, ES
mov KEEP_IP, BX ; here I save address of old interrupt handler
CLI
push DS
mov dx, offset myint
mov ax, seg myint
mov ds,ax
mov AH,25h
mov AL,09h
int 21h ; here I set new interrupt handler
pop DS
STI
call mytask ; here I start mytask
jmp end123
myint proc far ; my keyboard interrupt handler
push ds
push ax
push dx
push cx
mov ah,09h
mov dx, offset IHandlerMessage
int 21h
pop cx
pop dx
pop ax
pop ds
push ax
mov al,20h
out 20h,al
pop ax
iret
myint endp
end123:
CLI
push DS
mov DS, [KEEP_CS]
mov DX, [KEEP_IP]
mov AH,25h
mov AL,09h
int 21h ; here I set old interrupt handler again, though it is
pop DS ; not needed in this program
STI
mov ah,4ch
int 21h
END
答案 0 :(得分:4)
没有任何DOS功能可重入。
这意味着如果CPU正在执行DOS" s#34;写字符串"函数并被进入(使用)"写入字符串"的IRQ中断。功能;你可以期待内部变量等中断的"写字符串"已经使用过的可能会被第二个"写入字符串";和数据,第二个"写字符串"期望在默认状态下查找可能处于不同的状态,因为第一个"写字符串"正在使用它。
更具体地说;我怀疑当你调用DOS函数时DOS会切换到自己的内部堆栈(因为它不知道调用者堆栈中剩余多少空间);所以,当DOS重新进入"它切换到已经在使用的相同堆栈并覆盖堆栈上的所有数据(可能包括IRQ处理程序需要用来返回它中断的代码的数据)。