這份 .model small 組合語言程式展示了如何在 DOS 環境下,透過 INT 21h 功能 2Ah (取日期) 與 2Ch (取時間) 獲取原始二進位數值,再以自訂的 todec 子程式將其轉換為定寬、前置補零的 ASCII 字串,最後呼叫 INT 21h, AH=09h 列印格式化結果。程式結構清晰,資料段與程式碼段分離,子程式模組化良好,是學習「系統呼叫 → 資料轉換 → 格式化輸出」完整流程的優秀教材。
.data 區預先定義兩個模板字串,內含佔位符:
date_str db "Current date is: yyyy-mm-dd", 0Ah, 0Dh, "$" time_str db "Current time is: hh.mm.ss:xx", 0Ah, 0Dh, "$"程式執行時會直接修改這兩個緩衝區中佔位符的位置 (透過
DI指標),將轉換後的數字寫入,最後一次列印整串,避免多次呼叫 DOS 列印函數。輔助變數:
min_size dw 2:最小輸出寬度 (不足補零)padd_chr db '0':補位字元todec 接收 AX = 待轉數值,DI = 目標緩衝區位址,輸出定寬 ASCII 字串:
DIV BX (BX=10),餘數入堆疊,商繼續除,直到商為 0。計數器 CX 記錄位數。min_size,以 padd_chr 填補高位。'0' 轉 ASCII,寫入 DS:[DI] 並遞增 DI。AX, BX, CX, DX。此演算法通用於 8/16/32 位元數值 (視 AX 或 DX:AX 而定),且無分支預測失誤風險 (固定迴圈),極適合嵌入式環境。
日期 (INT 21h, AH=2Ah):回傳 CX=年, DH=月, DL=日。程式依序呼叫 todec 填入 yyyy-mm-dd 模板。
時間 (INT 21h, AH=2Ch):回傳 CH=時, CL=分, DH=秒, DL=百分秒。同樣依序填入 hh.mm.ss:xx。
關鍵指令序列:
lea di, date_str
add di, 17 ; 定位至第一個 'y'
mov ax, cx ; 年份在 CX
call todec
inc di ; 跳過 '-'
xor ax, ax
mov al, dh ; 月份
call todec
inc di ; 跳過 '-'
xor ax, ax
mov al, dl ; 日期
call todec
簡潔包裝 INT 21h, AH=09h:
print proc
push ax
push ds
mov ax, @data
mov ds, ax ; 確保 DS 指向資料段
mov ah, 09h
int 21h
pop ds
pop ax
ret
print endp
注意:INT 21h, 09h 要求 DS:DX 指向以 $ 結尾的字串,故列印前必須重載 DS (因前序操作可能改變 DS)。
.model small
.stack
.data
date_str db "Current date is: yyyy-mm-dd", 0Ah, 0Dh, "$"
time_str db "Current time is: hh.mm.ss:xx", 0Ah, 0Dh, "$"
min_size dw ?
padd_chr db ?
.code
main proc
mov ax, seg @data
mov ds, ax
mov [min_size], 02h
mov [padd_chr], '0'
mov ah, 2Ah
int 21h
lea di, date_str
add di, 17
mov ax, cx
call todec
inc di
xor ax, ax
mov al, dh
call todec
inc di
xor ax, ax
mov al, dl
call todec
lea di, time_str
add di, 17
mov ah, 2Ch
int 21h
xor ax, ax
mov al, ch
call todec
inc di
mov al, cl
call todec
inc di
mov al, dh
call todec
inc di
mov al, dl
call todec
mov dx, offset date_str
call print
mov dx, offset time_str
call print
mov ax, 4C00h
int 21h
main endp
todec proc
push ax
push bx
push cx
push dx
xor cx, cx
mov bx, 10
decloop:
xor dx, dx
div bx
inc cx
push dx
cmp ax, 0
jnz decloop
mov bx, [min_size]
mov dl, [padd_chr]
padd_result:
cmp cx, bx
jge poploop
mov byte ptr ds:[di], dl
inc di
dec bx
jmp padd_result
poploop:
pop dx
add dl, '0'
mov byte ptr ds:[di], dl
inc di
dec cx
jnz poploop
pop dx
pop cx
pop bx
pop ax
ret
todec endp
print proc
push ax
push ds
mov ax, @data
mov ds, ax
mov ah, 09h
int 21h
pop ds
pop ax
ret
print endp
end main
這份程式碼雖簡短,卻涵蓋了組合語言程式設計中「資料取得 → 轉換 → 格式化 → 輸出」的完整生命週期,極適合作為入門到進階的銜接教材。