📄 zhongweek.asm
字号:
DATA SEGMENT
;----------------------------父菜单-----------------------
FMENU DB 0AH,0DH,' **************** WELCOM **************** '
DB 0AH,0DH,' * %%%%%%%%%%%%%%%%%%%% * '
DB 0AH,0DH,' * Operations: * '
DB 0AH,0DH,' * [1]. Log On * '
DB 0AH,0DH,' * [2]. Get Day-in-Week * '
DB 0AH,0DH,' * [3]. Adiminitrator * '
DB 0AH,0DH,' * [4]. Exit * '
DB 0AH,0DH,' * * '
DB 0AH,0DH,' ****************************************$'
DB 0AH,0DH,'Please select the operation(1-4):$'
;----------------------------子菜单------------------------
CMENU DB 0AH,0DH,' **************** WELCOM **************** '
DB 0AH,0DH,' * ^ ------ ^ * '
DB 0AH,0DH,' * Operations: * '
DB 0AH,0DH,' * [1]. Reset Start Day * '
DB 0AH,0DH,' * [2]. Reset Passwords * '
DB 0AH,0DH,' * [3]. Exit * '
DB 0AH,0DH,' * * '
DB 0AH,0DH,' * * '
DB 0AH,0DH,' ****************************************$'
DB 0AH,0DH,'Please select the operation(1-3):$'
;-----------------------------------------------------------
Table DB 31,28,31,30,31,30,31,31,30,31,30;月/天数
Title DB 0AH,0DH,'TheDay-in-Week is:$' ;输出状态提示
Logon DB 0AH,0DH,'Please Log On!$' ;登陆状态提示
Error DB 0AH,0DH,'Input Error!$' ;错误状态提示
Passwords DB 80 DUP<8,'C','S','Q','-','1','9','8','6'> ;原始密码,第一个记录密码长度
Passtip1 DB 0AH,0DH,'Please enter the passwords(Maxsize=80):$';密码设置提示
Sdate DB 0 ;输入密码状态标志
Passtip2 DB 0AH,0DH,'Please enter the new passwords(Maxsize=80):$'
Yes DB 0AH,0DH,'OK!$' ;设置状态
Tipsetday DB 0AH,0DH,'Format:Year/Month/Day/Postion-Week$';输入格式提示
Daystart DW 2006,12,21,4 ;初始:年/月/日/星期X
BUF DB 80 ;键盘输入缓冲区
DB ?
DB 80 DUP(?)
Today DW 4 DUP(0) ;当前输入的待查询日期
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
;-----主函数-类While(1)循环----
MAIN:MOV AX,DATA
MOV DS,AX
CALL F
;------------------------------
;---------------父菜单功能实现-子程序1-------------------
F PROC NEAR
PUSH DX ;现场保护DX,菜单项
PUSH AX ;现场保护AX,操作码
FREPIT:LEA DX,FMENU ;载入父菜单
CALL DISTR ;屏幕显示父菜单
MOV AH,1 ;选择服务项
INT 21H
SUB AL,30H ;执行选择命令,数据校验
CMP AL,1 ;必须先登陆,从菜单起始下标起
JNZ TO_L ;后备的身份校验
CMP AL,2
JZ TO_P ;键入日期的位置---------主功能
CMP AL,3
JZ TO_C ;进入管理区
CMP AL,4
JZ TO_E ;退出
CALL TO_D ;默认操作
POP AX ;现场恢复
POP DX
JMP FREPIT ;返回主菜单
TO_L:LEA DX,Logon
CALL DISTR
JMP FREPIT ;返回主菜单
TO_P:LEA DX,Tipsetday;输入日期提示
CALL DISTR
CALL OUTROW ;输出换行
PUSH CX
PUSH AX
MOV CX,4
LP1: LEA DX,BUF ;键盘依次输入年/月/日/星期
MOV AH,10
INT 21H
PUSH CX ;开始码制转换
PUSH BX
MOV CX,BUF[1];输入的字符串长度
MOV DL,10
MOV SI,2 ;从第二个字节开始存放的
L1:MOV AL,BUF[SI]
SUB AL,30H ;转换为数值型
CMP SI,2 ;是否为原数的第一位
INC SI ;后移
JNZ A1
MOV BL,AL ;根据算法需求,保存第一位
JMP L1
A1:XCHG AL,BL;刚输入的值与前几位值交换存储
MUL DL
ADD AL,BL
MOV BL,AL
LOOP L1 ;子循环,缺点:只可转换一个正数( < 2560 )
POP BX
POP CX
MOV Today[4-CL],AX;保存经转换后的数字
LOOP LP1
MOV DX,0 ;测试初始年是否为闰年 ;算法:1> 据已知的Daystart(设为s年sx月sy日si星期数)推断该年是否为闰年;
MOV AX,Daystart[0] ; 2> 并推断该年1月1日的星期数,S=((累加sx)+sy-1)%7(1<=i<=sx),S1.1=(si+7-S)%7
MOV CL,4 ; 3.1>当待求E>S时,推断e年1月1日的星期数为
DIV CL ; (S1.1+闰年数+(e-s))%7, 其中,闰年数=(|e-s|)/4+(e%4&&s%4)
CMP DL,0 ;确定是否闰年 ; 3.2>当待求e<s时,推断e年1月1日的星期数为
JNZ FDAY ; (S1.1+7-(s-e+闰年数)%7)%7
MOV TABLE[1],TABLE[1]+1;若为闰年则二月29天 ; 4>计算e年ex月ey日的星期数为
MOV AX,0 ; (ei+ey+i)%7
MOV CX,Today[1]-1
FDAY:ADD AL,TABLE[CL] ;求si之和
LOOP FDAY
ADD AL,PTR BYTE Today[5]-1;求累加si +sy-1
MOV DX,0
MOV CL,7
DIV CL ;S
MOV CX,Daystart[3]
ADD DH,CL+7-DL
;MOV DL,0
;MOV PTR BYTE Today[7],DH
CMP DH,7
JA S1 ;S1.1的星期数DH
CMP Today[0],Daystart[0];比较E与S大小
JA S2
LEA DX,Title
CALL DISTR
ADD Today[3],30H;显示星期数
MOV DL,Today[3]
INT 21H
POP AX ;现场恢复
POP CX
S1:SUB DH,7
S2:SUB
S3:
JMP FREPIT ;返回主菜单
TO_C:CALL P_WORD ;验明身份
CALL C ;进入子菜单
JMP FREPIT ;返回主菜单
TO_E:CALL EXIT ;退出系统
TO_D:LEA DX,Error
CALL DISTR
JMP FREPIT ;返回主菜单
T :RET ;返回主调函数
F ENDP
;-----------------子菜单功能实现-子程序2-----------------
C PROC NEAR
PUSH DX ;现场保护DX,菜单项
PUSH AX ;现场保护AX,操作码
CREPIT:LEA DX,CMENU ;载入子菜单
CALL DISTR ;屏幕显示子菜单
MOV AH,1 ;选择服务项
INT 21H
SUB AL,30H ;执行选择命令,数据校验
CMP AL,1
JNZ R_S ;重设初始日期
CMP AL,2
JZ R_P ;重设密码
CMP AL,3
JZ R_E ;退出
CALL R_D ;默认操作
R_S:LEA DX,Tipsetday
CALL DISTR ;换行
PUSH CX
PUSH AX
MOV CX,4
LP1: LEA DX,BUF ;键盘依次输入年/月/日/星期
MOV AH,10
INT 21H
PUSH CX ;开始码制转换
PUSH BX
MOV CX,BUF[1];输入的字符串长度
MOV DL,10
MOV SI,2 ;从第二个字节开始存放的
L1:MOV AL,BUF[SI]
SUB AL,30H ;转换为数值型
CMP SI,2 ;是否为原数的第一位
INC SI ;后移
JNZ A1
MOV BL,AL ;根据算法需求,保存第一位
JMP L1
A1:XCHG AL,BL ;刚输入的值与前几位值交换存储
MUL DL
ADD AL,BL
MOV BL,AL
LOOP L1 ;子循环,缺点:只可转换一个正数( < 2560 )
POP BX
POP CX
MOV Daystart[4-CL],AX;保存经转换后的数字
LOOP LP1
POP AX ;现场恢复
POP CX
LEA DX,Yes ;设置成功!
CALL DISTR
JMP CREPIT ;返回子菜单
R_P:CALL P_WORD ;验明身份
CMP Sdate,1
JNZ R ;返回主调函数
LEA DX,Passtip2 ;密码设置提示
CALL DISTR
PUSH CX
MOV CX
MOV SI,1
ON:MOV AH,8 ;无回显密码输入
CMP AL,0DH ;是否为回车?
JZ Y
MOV Passwords[SI],AL ;保存密码
INC SI
LOOP ON ;直到空格或输入超过80
MOV Passwords[0],SI-1;记录新密码长度
Y:LEA DX,Yes
CALL DISTR
POP CX
JMP R ;返回主调函数
R_E:CALL EXIT ;退出系统
R_D:LEA DX,Error
CALL DISTR
JMP CREPIT ;返回子菜单
R :RET
C ENDP
;---------------------------------------------------------------
;-----------------------------------
;密码验证
P_WORD PROC NEAR
PUSH CX ;现场保护
MOV CX,3 ;容许密码输入的最大次数
LOP:PUSH DX ;现场保护
PUSH AX
PUSH CX
MOV CX,Passwords[0];密码长度
MOV SI,1
LEA DX,Passtip1
CALL DISTR ;连续输入直到回车
LOP1:MOV AH,8 ;无回显密码输入
CMP AL,0DH ;是否为回车?
JNZ GO_ON ;逐位验证密码
MOV DI,1 ;比较起始地址
COMP:CMP Passwords[DI],BUF[DI]
JNZ WRONG
LOOP COMP
LEA DX,Yes ;密码正确
CALL DISTR
MOV Sdate,1 ;输入密码正确标志
JMP R ;返回主调函数
GO_ON:MOV BUF[SI],AL ;逐位输入缓冲区
JMP LOP1
WRONG:LEA DX,Error ;输出密码错误
CALL DISTR
CALL OUTROW
POP CX ;现场恢复
POP AX
POP DX
LOOP LOP ;三次未通过则自动退出
POP CX
R: RET
P_WORD ENDP
;-----------------------------------
;退出系统
EXIT PROC NEAR
MOV AH,4CH
INT 21H
RET
EXIT ENDP
;-----------------------------------
;输出换行
OUTROW PROC NEAR
PUSH DX
MOV DL,0AH
MOV AH,2
INT 21H
POP DX
RET
OUTROW ENDP
;------------------------------------
;输出字符串
DISTR PROC NEAR
MOV AH,9
INT 21H
RET
DISTR ENDP
;------------------------------------
CODE ENDS
END MAIN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -