9

MS-DOS のアセンブリ (16 ビット) で TSR (Terminate-Stay-Resident) プログラム (一般的に) を作成しようとしています。TSR に関するウィキペディアのページと、特に DOS での使用に関するページを読みました (ただし、アセンブリではなく C で教えているようです)。大量の DOS 割り込みに関するドキュメントがあるサイトを調べたところ、これこれ、および TSR プログラムに最も関連する別のサイトが見つかりました。新しいユーザーとして投稿に最大 2 つのハイパーリンクを設定できるため、すべてのリンクを投稿することはできません。

そこで、NASM のリアル モード フラット モデル (.COM ファイル形式) で (一見) 非常に単純な TSR プログラムを作成してみました。コードは次のとおりです。

[BITS 16]
[ORG 0x0100]

[SECTION .text]

Start:
; Get current interrupt handler for INT 21h
mov AX,3521h                ; DOS function 35h GET INTERRUPT VECTOR for interrupt 21h
int 21h                     ; Call DOS  (Current interrupt handler returned in ES:BX)

mov WORD [v21HandlerSegment],ES     ; Store the current INT 21h handler segment
mov WORD [v21HandlerOffset],BX      ; Store the current INT 21h handler offset

; Write new interrupt handler for INT 21h
mov AX,2521h                ; DOS function 25h SET INTERRUPT VECTOR for interrupt 21h
mov DX,TSRStart             ; Load DX with the offset address of the start of this TSR program
;   DS already contains the segment address, it is the same as CS in this .COM file
int 21h                     ; Override the INT 21h handler with this TSR program

; The TSR program will be called even when this portion uses INT 21h to terminate and stay resident
mov AX,3100h                ; DOS function TSR, return code 00h
mov DX,00FFh                ; I don't know how many paragraphs to keep resident, so keep a bunch
int 21h                     ; Call our own TSR program first, then call DOS

TSRStart:
push WORD [v21HandlerSegment]       ; Push the far address of the original 
push WORD [v21HandlerOffset]        ;   INT 21h handler onto the stack
retf                                ; Jump to it!


[SECTION .data]
v21HandlerSegment dw 0000h
v21HandlerOffset  dw 0000h

これをアセンブルして DOS 内で実行すると、DOS プロンプトに戻る代わりに、システムがハングします (ハードウェア カーソルが最後のプロンプトの下で点滅するだけで、アクティビティは発生しません)。メモリガベージが実行されている可能性があると思いますが、要点はわかります。

どなたか、このコードの問題点を突き止めたり、DOS で TSR をコーディングするための一般的なアドバイスを提供したりしていただけませんか? 事前に感謝します。どんな助けでも大歓迎です!

4

2 に答える 2

6

私はそれを考え出した。さらにいくつかのソースを調べたところ、次のコードが見つかりました。

push WORD [v21HandlerSegment]       ; Push the far address of the original 
push WORD [v21HandlerOffset]        ;   INT 21h handler onto the stack

次のようにする必要があります。

push WORD [CS:v21HandlerSegment]       ; Push the far address of the original 
push WORD [CS:v21HandlerOffset]        ;   INT 21h handler onto the stack

これらのメモリ参照は、TSR の呼び出し元から設定されていないデータ セグメントから参照されているためです。基本的に、私は他のデータブロックからデータを参照していました...

これは、次のように CS を DS に入れる (そして DS の元の値を戻す) ことによっても実現できます。

push DS
push CS
pop DS
; Memory references....
pop DS
于 2011-07-29T18:48:36.897 に答える