.MODEL SMALL
.STACK 100H
.DATA
; 时间显示相关
am_str DB 'A.M.$'
pm_str DB 'P.M.$'
colon DB ':$'
dot DB '.$'
space DB ' $'
comma DB ', $'
newline DB 0DH, 0AH, '$' ; 回车换行
; 星期名称指针表
weekday_ptrs DW SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
SUNDAY DB 'Sunday$'
MONDAY DB 'Monday$'
TUESDAY DB 'Tuesday$'
WEDNESDAY DB 'Wednesday$'
THURSDAY DB 'Thursday$'
FRIDAY DB 'Friday$'
SATURDAY DB 'Saturday$'
; 月份名称指针表(修复:补齐12个月份)
month_ptrs DW JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE
DW JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
JANUARY DB 'January$'
FEBRUARY DB 'February$'
MARCH DB 'March$'
APRIL DB 'April$'
MAY DB 'May$'
JUNE DB 'June$'
JULY DB 'July$'
AUGUST DB 'August$'
SEPTEMBER DB 'September$'
OCTOBER DB 'October$'
NOVEMBER DB 'November$'
DECEMBER DB 'December$'
; 时间日期缓存
hour_12 DB ?
am_pm DB ? ; 0=A.M., 1=P.M.
; 日期临时变量(修复非法内存访问)
current_weekday DB ?
current_day DB ?
current_month DB ?
current_year DW ?
.CODE
START:
MOV AX, @DATA
MOV DS, AX
; 设置文本模式 - 修复内存访问冲突
MOV AX, 0003H
INT 10H
MAIN_LOOP:
; 设置光标到(0,0)
XOR DX, DX
CALL SET_CURSOR
; 显示日期
CALL SHOW_DATE
; 设置光标到(1,0)
MOV DH, 1
XOR DL, DL
CALL SET_CURSOR
; 显示时间
CALL SHOW_TIME
; 检查按键 (修复:使用正确的方法检查按键)
MOV AH, 01H
INT 16H
JNZ EXIT_PROGRAM ; 有按键则退出
; 短暂延时(约55ms) - 修复百分秒不更新问题
MOV CX, 5 ; 减少延迟时间
MOV DX, 86A0H
MOV AH, 86H
INT 15H
JMP MAIN_LOOP
EXIT_PROGRAM:
; 清空键盘缓冲区
MOV AH, 0CH
MOV AL, 0
INT 21H
; 设置光标位置 (DH=行, DL=列)
SET_CURSOR PROC
MOV AH, 02H
MOV BH, 0 ; 页号0
INT 10H
RET
SET_CURSOR ENDP
; 显示日期子程序 - 完全重构
SHOW_DATE PROC
; 获取日期 (INT 21H, AH=2AH)
MOV AH, 2AH
INT 21H ; 返回: AL=星期几(0=日), CX=年, DH=月, DL=日
; 保存日期值到内存变量 (修复非法内存访问)
MOV current_weekday, AL
MOV current_day, DL
MOV current_month, DH
MOV current_year, CX
; 显示星期 (修复索引计算错误)
XOR AX, AX
MOV AL, current_weekday ; 星期索引(0-6)
MOV SI, AX
SHL SI, 1 ; 乘以2 (指针大小)
MOV DX, weekday_ptrs[SI]
MOV AH, 09H
INT 21H
; 显示逗号
MOV DX, OFFSET comma
INT 21H
; 显示月份 (修复月份索引错误)
XOR AX, AX
MOV AL, current_month ; 月份(1-12)
DEC AL ; 调整为0-based索引
MOV SI, AX
SHL SI, 1 ; 乘以2 (指针大小)
MOV DX, month_ptrs[SI]
MOV AH, 09H
INT 21H
; 显示空格
MOV DX, OFFSET space
INT 21H
; 显示日 (修复日期值处理错误)
XOR AX, AX
MOV AL, current_day
CALL PRINT_DECIMAL
; 显示逗号
MOV DX, OFFSET comma
MOV AH, 09H
INT 21H
; 显示年
MOV AX, current_year
CALL PRINT_DECIMAL
RET
SHOW_DATE ENDP
; 显示时间子程序 - 修复百分秒显示问题
SHOW_TIME PROC
; 获取时间 (INT 21H, AH=2CH)
MOV AH, 2CH
INT 21H ; 返回: CH=时, CL=分, DH=秒, DL=百分秒
; 保存时间值 (修复百分秒处理)
PUSH DX ; 保存秒/百分秒
PUSH CX ; 保存时/分
; 转换为12小时制
MOV AL, CH ; 小时
CMP AL, 0
JE HOUR_12_AM
CMP AL, 12
JB HOUR_AM
JE HOUR_12_PM
SUB AL, 12
MOV [am_pm], 1
JMP HOUR_DONE
HOUR_12_AM:
MOV AL, 12
MOV [am_pm], 0
JMP HOUR_DONE
HOUR_AM:
MOV [am_pm], 0
JMP HOUR_DONE
HOUR_12_PM:
MOV AL, 12
MOV [am_pm], 1
HOUR_DONE:
MOV [hour_12], AL
; 显示小时
MOV AL, [hour_12]
CALL PRINT_TWO_DIGITS
; 显示冒号
MOV DX, OFFSET colon
MOV AH, 09H
INT 21H
; 显示分钟
POP CX ; 恢复时/分
MOV AL, CL
CALL PRINT_TWO_DIGITS
; 显示冒号
MOV DX, OFFSET colon
MOV AH, 09H
INT 21H
; 显示秒 (修复百分秒处理)
POP DX ; 恢复秒/百分秒
PUSH DX ; 重新保存百分秒
MOV AL, DH ; 秒
CALL PRINT_TWO_DIGITS
; 显示点
MOV DX, OFFSET dot
MOV AH, 09H
INT 21H
; 显示百分秒 (修复:直接从原始值获取)
POP DX ; 恢复百分秒
MOV AL, DL ; 百分秒
CALL PRINT_TWO_DIGITS
; 显示空格
MOV DX, OFFSET space
MOV AH, 09H
INT 21H
; 显示A.M./P.M.
MOV DX, OFFSET am_str
CMP [am_pm], 1
JNE SHOW_AMPM
MOV DX, OFFSET pm_str
SHOW_AMPM:
MOV AH, 09H
INT 21H
RET
SHOW_TIME ENDP
; 打印两位数(AL=0-99) - 修复寄存器冲突
PRINT_TWO_DIGITS PROC
PUSH AX ; 保存原始值
AAM ; AH=十位, AL=个位
ADD AX, 3030H
MOV BX, AX ; 保存转换结果
MOV DL, BH ; 显示十位
MOV AH, 02H
INT 21H
MOV DL, BL ; 显示个位
INT 21H
POP AX
RET
PRINT_TWO_DIGITS ENDP
; 打印十进制数(AX=0-65535) - 修复寄存器冲突
PRINT_DECIMAL PROC
PUSH BX
PUSH CX
PUSH DX
PUSH SI
MOV SI, 10 ; 除数
XOR CX, CX ; 计数器(数字个数)
DECIMAL_LOOP:
XOR DX, DX
DIV SI ; AX / 10 -> AX=商, DX=余数
ADD DL, '0' ; 转为ASCII
PUSH DX ; 保存数字
INC CX
TEST AX, AX
JNZ DECIMAL_LOOP
PRINT_LOOP:
POP DX ; 取出数字
MOV AH, 02H
INT 21H
LOOP PRINT_LOOP
POP SI
POP DX
POP CX
POP BX
RET
PRINT_DECIMAL ENDP
END START
上面代码成功显示了时间和日期功能,但是输出格式为:日期和时间是两行输出,我需要把它们放在一行显示,日期放在时间后面,中间隔一个逗号,且删除月份和日期中间的逗号,用空格代替。例如,图片输出为:
Thursday,June,26,2025
04:51:18.88 P.M.
而我需要的输出格式为:04:51:18.88 P.M.,Thursday,June 26,2025 请修改代码