📄 汇编实现月历.asm
字号:
DATAS SEGMENT
A1 DB "=====================================$"
A2 DB "*** * * * * Calendar * * * * ****$"
A3 DB "designer: Wubinghui $"
A4 DB "Please input the date:$"
A5 DB "Please input the date like :20090101$"
STR1 DB 9
DB ?
DB 9 DUP(?)
A6 DW 0
A7 DB 0
A8 DB "Date:$"
B DW ?
C1 DW 0
C2 DB 0
G DB 0
N DB ?
P DW ?
Y DB ?
WEEK DB "SUN MON TUE WED THU FRI SAT$"
YEAR DW ?
MONTH DW ?
DAY DW ?
WRONG DB "The date you input is wrong!Please try again$"
ROW DB 1
BUF1 DB 31,?,31,30,31,30,31,31,30,31,30,31
BUF2 DB 1,2,3,4,5,6,7,8,9,10,11,12
BUF3 DB ' 1',0AH,0DH,'$'
DB ' 2',0AH,0DH,'$'
DB ' 3',0AH,0DH,'$'
DB ' 4',0AH,0DH,'$'
DB ' 5',0AH,0DH,'$'
DB ' 6',0AH,0DH,'$'
DB ' 7',0AH,0DH,'$'
DB ' 8',0AH,0DH,'$'
DB ' 9',0AH,0DH,'$'
DB '10',0AH,0DH,'$'
DB '11',0AH,0DH,'$'
DB '12',0AH,0DH,'$'
DB '13',0AH,0DH,'$'
DB '14',0AH,0DH,'$'
DB '15',0AH,0DH,'$'
DB '16',0AH,0DH,'$'
DB '17',0AH,0DH,'$'
DB '18',0AH,0DH,'$'
DB '19',0AH,0DH,'$'
DB '20',0AH,0DH,'$'
DB '21',0AH,0DH,'$'
DB '22',0AH,0DH,'$'
DB '23',0AH,0DH,'$'
DB '24',0AH,0DH,'$'
DB '25',0AH,0DH,'$'
DB '26',0AH,0DH,'$'
DB '27',0AH,0DH,'$'
DB '28',0AH,0DH,'$'
DB '29',0AH,0DH,'$'
DB '30',0AH,0DH,'$'
DB '31',0AH,0DH,'$'
DATAS ENDS
STACKS SEGMENT
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV AH,0 ;设置显示方式
MOV AL,3 ;80*25彩色文本方式
INT 10H
MOV AH,6
MOV AL,0
MOV CH,0
MOV CL,0 ;清整个屏幕
MOV DH,80
MOV DL,80
MOV BH,10110000B ;前四位定义背景色,后四位定义前景色
INT 10H
MOV DH,ROW
MOV DL,2
CALL GBIAO
LEA DX,A1
CALL NINE
ADD ROW,2
MOV DH,ROW
MOV DL,1
CALL GBIAO
LEA DX,A2
CALL NINE
ADD ROW,2
MOV DH,ROW
MOV DL,8
CALL GBIAO
LEA DX,A3
CALL NINE
ADD ROW,2
MOV DH,ROW
MOV DL,1
CALL GBIAO
LEA DX,A5
CALL NINE
ADD ROW,2
REINPUT:MOV AH,6 ;输入日期显示蓝色
MOV AL,0
MOV CH,ROW
MOV CL,23
MOV DH,ROW
MOV DL,30
MOV BH,10110001B
INT 10H
MOV DH,ROW
MOV DL,1
CALL GBIAO
LEA DX,A4
CALL NINE
MOV DH,ROW
MOV DL,23
CALL GBIAO
LEA DX,STR1 ;输入日期,保存在缓冲区STR1中
MOV AH,10
INT 21H
ADD ROW,2
LEA DI,STR1+2 ;DI指向日期输入串的首地址
MOV CL,4
MOV AX,0
P1: MOV BL,[DI] ; 取字符送到BL
SUB BL,30H ;字符减去30H,转化为真值
MOV BH,0
MOV P,10
MUL P
ADD AX,BX
INC DI ;DI指向下一个字符
DEC CX ;长度减一
JNZ P1
MOV YEAR,AX
CALL PR ;调用判断平年还是闰年的程序
JC L1 ;有进位,借位,跳转到L1,输出闰年,否则顺序执行,是平年
LEA DI,BUF1
MOV [DI+1],BYTE PTR 28 ;平年把28送入BUF1中
JMP L2
L1:
LEA DI,BUF1
MOV [DI+1],BYTE PTR 29 ;闰年把29送入BUF1中
L2:
LEA DI,STR1+6
MOV CL,2
MOV AX,0
P2: MOV BL,[DI]
SUB BL,30H
MOV BH,0
MOV P,10
MUL P
ADD AX,BX
INC DI
DEC CX
JNZ P2
MOV MONTH,AX ;获得月份值
LEA DI,STR1+8
MOV CL,2
MOV AX,0
P3: MOV BL,[DI]
SUB BL,30H
MOV BH,0
MOV P,10
MUL P
ADD AX,BX
INC DI
DEC CX
JNZ P3
MOV DAY,AX ;获得输入的日数
CMP MONTH,1 ;月份<1,报错
JC ERROR
CMP MONTH,13 ;月份>12,报错
JNC ERROR
CMP DAY,1
JC ERROR
CALL GETN ;显示日历,调用GETN子程序返回N的值,N为每月第一天是星期几
MOV DI,OFFSET BUF1
DEC MONTH
DEC MONTH
ADD DI,MONTH ;取出每个月的天数--->G
MOV CL,[DI]
MOV G,CL
CMP BYTE PTR DAY,CL ;输入的天如果超过这个月的最大天数,报错
JA ERROR
MOV DH,ROW
MOV DL,10
CALL GBIAO
LEA DX,A8
CALL NINE
MOV DH,ROW
MOV DL,16
CALL GBIAO
LEA DI,STR1+2
MOV CL,8
MOV AX,0
DATE: MOV BL,[DI]
MOV DL,BL
MOV AH,2
INT 21H
INC DI
DEC CX
JNZ DATE
ADD ROW,1
MOV AH,6
MOV AL,0
MOV CH,ROW
MOV CL,3
MOV DH,ROW
MOV DL,0
MOV BH,10110100B
INT 10H ;SUN SAT设置红色
MOV AH,6
MOV AL,0
MOV CH,ROW
MOV CL,30
MOV DH,ROW
MOV DL,33
MOV BH,10110100B
INT 10H
MOV DH,ROW
MOV DL,0
CALL GBIAO
LEA DX,WEEK
CALL NINE ;显示SUN*******************SAT
INC ROW
MOV SI,OFFSET BUF3
MOV AL,5
MUL N
MOV B,AX
CMP B,35 ;如果每个月一号是星期天,显示一号的行号减2
JC POS
SUB ROW,1
POS: MOV DH,ROW ;每个月的一号的光标位置
MOV DL,BYTE PTR B
CALL GBIAO
MOV A7,31
CMP DL,A7
JBE POS1 ;DL<31,跳转到POS1,否则行加1,列从0开始
ADD ROW,1 ;两行日期间隔
MOV AX,0
MOV B,AX
MOV AH,6 ;日历周末设置红色显示
MOV AL,0
MOV CH,ROW
MOV CL,3
MOV DH,ROW
MOV DL,0
MOV BH,10110100B
INT 10H
JMP POS
POS1: CMP DL,30 ;周六的日历显示红色
JC NORED
MOV AH,6
MOV AL,0
MOV CH,ROW
MOV CL,30
MOV DH,ROW
MOV DL,33
MOV BH,10110100B
INT 10H
NORED: MOV DX,SI
CALL NINE ;在当前光标位置显示数字
ADD SI,5
ADD B,5 ;两个日期的显示距离
DEC G
JNZ POS
JMP EXIT
ERROR: DEC ROW
MOV DH,ROW
MOV DL,1
CALL GBIAO
LEA DX,WRONG
CALL NINE
INC ROW
JMP REINPUT
EXIT: MOV AH,4CH
INT 21H
GBIAO PROC
PUSH AX
PUSH BX
MOV AH,2 ;2号功能调用
MOV BH,0
INT 10H ;定光标
POP BX
POP AX
RET
GBIAO ENDP
NINE PROC
PUSH AX
MOV AH,9 ;9号功能调用
INT 21H
POP AX
RET
NINE ENDP
PR PROC ;判断是平年还是闰年
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV AX,YEAR
MOV CX,AX
MOV DX,0
MOV BX,4
DIV BX
CMP DX,0 ;DX中为余数
JNZ B1
MOV AX,CX
MOV BX,100
DIV BX
CMP DX,0
JNZ B2
MOV AX,CX
MOV BX,400
DIV BX
CMP DX,0
JZ B2
B1: CLC ;CF=0
JMP B3
B2: STC ;CF=1
B3: POP DX
POP CX
POP BX
POP AX
RET
PR ENDP
GETN PROC ;获得这个月的一号是星期几
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV BL,100
MOV AX,YEAR
DIV BL
MOV C2,AL
MOV Y,AH
MOV CL,2
MOV BL,C2
SHR BL,CL ;int(c/4)
SHL C2,1 ;2*c
SUB BL,C2
ADD BL,Y
SHR Y,CL ;int(y/4)
ADD BL,Y ;int(c/4)-2*c+y+int(y/4)
INC MONTH
CMP MONTH,3 ;是一月,转移
JC J1 ;是二月,转移
CMP MONTH,4
JC J1
XOR AH,AH
MOV AX,MONTH
MOV DX,13
MUL DX
MOV CX,5
DIV CX
XCHG AX,BX
CBW
XCHG AX,BX
ADD BX,AX ;int(c/4)-2*c+y+int(y/4)+int(13*(m+1)/5)
MOV AX,BX
MOV CL,7
IDIV CL
CMP AH,0
JG SKIPADD
ADD AH,7
SKIPADD:
MOV BL,AH
MOV N,BL
JMP J3
J1: MOV BL,100
MOV AX,YEAR
DIV BL
MOV C2,AL
MOV Y,AH
CMP Y,1 ;如果年份后两位是00,则前一年是99
JNC J2
ADD Y,100
J2: SUB Y,1
MOV CL,2
MOV BL,C2
SHR BL,CL
SHL C2,1
SUB BL,C2
ADD BL,Y
SHR Y,CL
ADD BL,Y
ADD MONTH,12
XOR AH,AH
MOV AX,MONTH
MOV DX,13
MUL DX
MOV CX,5
DIV CX
XCHG AX,BX
CBW
XCHG AX,BX
ADD BX,AX
MOV AX,BX
MOV CL,7
IDIV CL
CMP AH,0
JG SKIPADD1
ADD AH,7
SKIPADD1:
MOV BL,AH
MOV N,BL
SUB MONTH,12
J3: POP DX
POP CX
POP BX
POP AX
RET
GETN ENDP
CODES ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -