2017-12-10 8 views
0

自分自身のキーボード割り込みハンドラ(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

はたぶんタイプミスや不正なコピー/ペーストは - 私はあなたが 'MOV AL、1Cを使用..あなたは、AH MOV' 25h' 'MOV AL、09h' ' int型の21h'を行うことを意味だと思います'。 '1c'はシステムタイマーティックベクトルです。 –

+2

また、[DOSは再入可能ではありません](http://oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter_18/CH18-3.html)という事実にも心配する必要があります。したがって、DOS割り込み割り込みの途中でキーボード割り込みが発生すると、問題が発生する可能性があります。 –

+0

どのような環境であなたのコードを実行していますか? –

答えて

4

どのDOS機能もリエントラントではありません。

これは、CPUがDOSの "write string"関数の実行中で、 "write string"関数を入力(使用)するIRQによって中断された場合、中断された "書き込み文字列"が既に使用していた内部変数などは、第2の "書き込み文字列"によって破棄されることがあります。第2の「書込み文字列」がデフォルト状態で見つかると予想されるデータは、第1の「書込み文字列」がそれを使用しているため、異なる状態にある可能性がある。

具体的には、 DOS関数を呼び出すと、DOSが独自の内部スタックに切り替わることが疑わしいです(呼び出し元のスタックにどれくらいのスペースが残っているかわからないため)。したがって、DOSが「再入力」されると、すでに使用されているものと同じスタックに切り替わり、スタック上のすべてのデータを上書きします(IRQハンドラが中断したコードに戻るために必要なデータを含む可能性があります)。あなたのコードを開発しながら

関連する問題