DOS 可執行檔分 .COM(單段、≤64KB、起始 100H、載入快)與 .EXE(多段、無大小限制、載入慢、TSR 較麻煩)。
cseg segment
assume cs:cseg, ds:cseg
org 100h
start:
ret
cseg ends
end start
org 100h)、可執行代碼(此處僅 RET)、結束標記(end start 指定入口)。RET 機器碼 C3),因 .COM 無程式段前綴(PSP),DOS 載入時自動建立 PSP(0000H 起 256 位元組)。INT 27H 終止並駐留cseg segment
assume cs:cseg, ds:cseg
org 100h
start:
nop
done:
mov dx, offset done
int 27h
cseg ends
end start
INT 27H:以 DX 指向可用記憶體起始位置(相對 DS),DOS 更新載入基準指標,DX 之前區域永久駐留。INT 21H AH=31H:需指定保留段落數並回傳退出碼,較不直觀。DS=CS 為 .COM 載入預設,assume ds:cseg 僅告知編譯器,不產生代碼;執行時必須確保 DS=CS,否則失敗。cseg segment
assume cs:cseg, ds:cseg
org 100h
start:
jmp initialize
app_start:
nop ; 駐留程式主體放此處
initialize:
mov dx, offset initialize
int 27h
cseg ends
end start
start(100H)跳轉至 initialize,駐留主體置於 app_start~initialize 之間,僅初始化執行一次,主體常駐記憶體等待喚醒。start(100H),若將 initialize 放在 end 後會無法用 EXE2BIN 生成 .COM。TSR 駐留時 PSP 也被保留。理論上可在初始化時將整個程式下移 256 位元組覆蓋 PSP,但需處理:首次執行檢測、多 TSR 共存、長期未執行狀態。代碼超過 256 位元組即虧損。多數 TSR 不值得為此增加複雜度,保持簡潔優先。
TSR 必須掛載到事件源:鍵盤(INT 16H/硬體中斷)、時鐘(INT 1CH)、系統呼叫等。必須在安裝時建立喚醒管道,否則永遠無法被使用。IBM PC 事件驅動,攔截中斷向量讓我們的程式優先執行,成為應用程式與作業系統間的橋樑。
INT 16H 範例cseg segment
assume cs:cseg, ds:cseg
org 100h
start:
jmp Initialize
new_keyboard_io proc far
sti
nop
iret
new_keyboard_io endp
Initialize:
mov dx, offset new_keyboard_io
mov al, 16h
mov ah, 25h
int 21h ; 設定中斷向量
mov dx, offset Initialize
int 27h
cseg ends
end start
STI 開中斷,IRET 正確返回(恢復旗標)。雖此例多餘,但實戰中斷處理常式必備。AH=25H AL=中斷號 DS:DX=新處理器位址 設定向量。單純攔截不呼叫舊處理器會導致鍵盤輸入卡死(硬體中斷仍填滿隊列,但軟體中斷 INT 16H 讀不出)。必須模擬 INT 呼叫舊處理器:
Old_Keyboard_IO dd ? ; 雙字儲存舊向量(段:偏移)
new_keyboard_io proc far
sti
pushf ; 模擬 INT 壓入旗標
assume ds:nothing ; 告知編譯器 DS 不可靠
call Old_Keyboard_IO; 呼叫舊處理器
nop
iret
new_keyboard_io endp
Initialize:
assume cs:cseg, ds:cseg
mov bx, cs
mov ds, bx
mov al, 16h
mov ah, 35h
int 21h ; 取得舊向量 → ES:BX
mov word ptr Old_Keyboard_IO, bx
mov word ptr Old_Keyboard_IO[2], es
; 設定新向量...
int 27h
PUSHF + CALL 模擬 INT:舊處理器以 IRET 返回,控制權回我們程式,再 IRET 返回原調用者。assume ds:nothing 防止編譯器誤用 DS 產生錯誤定址,確保 call Old_Keyboard_IO 產生正確遠呼叫碼。修改 AH=0(讀字元)路徑:呼叫舊處理器取字元後,若 AL='y' 改 'Y',若 'Y' 改 'y',其他功能(AH=1,2)直接 JMP 舊處理器。執行後鍵盤輸入 y/Y 即互換,驗證攔截鏈路暢通。