在 DOS 環境下精確取得系統時間,是批次檔排程、定時觸發程式的基礎。本文解析一個完整的 TimeWait 範例,展示如何以條件組合同時支援 DOS INT 21h AH=2Ch 與 BIOS INT 1Ah AH=0 兩種取時方式,並包含命令列參數解析、鍵盤輪詢退出等實用技巧。
use_bios_flag EQU 1 ; 0=DOS, 1=BIOS
.MODEL TINY
.STACK 500
.CODE
透過 IF/ELSE/ENDIF 在組譯期決定呼叫哪個取時常式,生成的 .COM 檔無執行期分支開銷。
get_number從 PSP 80h 起解析 HH:MM 格式:
get_number 兩次分別取得時、分。number_check 驗證 ASCII 數字('0'~'9'),轉二進位並累加(十位×10+個位)。':' 與範圍(時 0-23、分 0-59)。CF=1 返回,主程式跳轉顯示用法訊息。wait_loopwait_loop:
; 掃描鍵盤,支援 F1 (3B00h) 或 ESC (1Bh) 退出
mov ah, 1
int 16h
jz wait_no_key
mov ah, 0
int 16h
cmp ax, 3B00h
je exit
cmp al, 1Bh
je exit
wait_no_key:
; 條件組合:取得目前時間
IF use_bios_flag
call get_time_of_day ; BIOS INT 1Ah
ELSE
mov ah, 2Ch
int 21h ; DOS INT 21h
ENDIF
; 比對 CH(時)、CL(分) 與目標值
cmp ch, wait_hour
jne wait_loop
cmp cl, wait_minute
jne wait_loop
get_time_of_day(原始碼中未列出完整實作,但標準做法為 INT 1Ah AH=0 回傳 CX:DX 為午夜起的時鐘節拍,需轉換為時/分/秒。)
| 項目 | 說明 |
|---|---|
| 模式 | .MODEL TINY → .COM 檔,單段 CS=DS=ES=SS |
| PSP 存取 | ES:80h 為命令列長度與資料 |
| 字串輸出 | INT 21h AH=09h,DX 指向 $ 結尾字串 |
| 程式結束 | INT 21h AH=4Ch |
| 錯誤訊息 | 含完整用法範例:TimeWait 11:30 |
TimeWait 14:30 && backup.batINT 21h AH=2Ch:回傳 CH=時, CL=分, DH=秒, DL=百分秒,易用但有函數呼叫開銷。INT 1Ah AH=0:回傳 CX:DX 節拍數(18.2Hz),需自行換算,但速度極快,適合高頻輪詢。masm timewait.asm
link timewait.obj /TINY
rename timewait.exe timewait.com
timewait 10:30
此範例不僅展示了時間取得的兩種經典路徑,更示範了組合語言在參數解析、條件編譯、即時輪詢等實戰技巧的綜合運用,是系統程式設計的優質教材。