首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

組合語言實作:取得並格式化顯示系統日期時間

     編輯:組合語言

前言:從原始中斷到可讀字串的完整路徑

這份 .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 (二進位轉十進位 ASCII)

todec 接收 AX = 待轉數值,DI = 目標緩衝區位址,輸出定寬 ASCII 字串:

  1. 反覆除以 10:DIV BX (BX=10),餘數入堆疊,商繼續除,直到商為 0。計數器 CX 記錄位數。
  2. 前置補零:若實際位數 < min_size,以 padd_chr 填補高位。
  3. 出堆疊存字元:餘數依序出堆疊,加 '0' 轉 ASCII,寫入 DS:[DI] 並遞增 DI。
  4. 完整保存/恢復 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

列印子程式:PRINT

簡潔包裝 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

教學價值總結

  • 示範 DOS 系統呼叫慣例 (AH 功能碼, 暫存器傳參, 旗標回傳)。
  • 展示 堆疊輔助演算法 (除法取餘入堆疊、出堆疊輸出) 實現位元組順序反轉。
  • 強調 段暫存器管理 (DS 切換、@data 取段址) 在 Small Model 下的關鍵性。
  • 模板字串就地修改技巧,減少 I/O 呼叫次數,提升效能。

這份程式碼雖簡短,卻涵蓋了組合語言程式設計中「資料取得 → 轉換 → 格式化 → 輸出」的完整生命週期,極適合作為入門到進階的銜接教材。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved