一、需求分析
要求:设计程序实现显示系统日期与时间,具体为:
A、程序运行时,先输出作者的相关信息,然后输出提示信息
B、输入大写字母’D’,可显示系统当前日期
C、输入大写字母’T’,可显示系统当前时间
D、输入大写字母’Q’,可结束程序。
在本设计中,首先设置显示方式为40*25文本方式,而后通过调用INT 10H的功能,显示提示信息。在显示信息提示下输入一 个字符,再通过调用INT 21H中断的功能,读取键盘输入的内容,如:若输入D,则设计程序代码一次读取系统日期年、月、日,并转换成ASCII码调用21H中断返回dos状态予以显示;若输入T,则设计程序代码一次读取系统时间时、分、秒,并转换成ASCII码调用21H中断返回dos状态予以显示;若输入Q,则退出程序;若不是相关字符,则显示错误。
二、总体设计
1、设计方案
图1:主程序设计流程图
2、系统功能结构
图2:系统功能结构框图
(1)MAIN程序
通过调用 IH 10H的功能,显示提示信息。在显示信息提示下输入一个字符,再通过调用INT21H中断的功能扫描键盘输入,读取键盘的状态,根据输入的字母,与字母“D”进行比较,若比较值不相等则去执行L1,否则响应按键D。其他如输入“T”和“Q”时同理。
(2)DATEDISPLAY PROC EAR子程序
即日期时间显示程序,以日期显示程序为例,通过读取系统的日期项如“年”通过调用CALL DATEDISPLAY把日期数值转换成相应的ASCII码字符,再通过调用DATEDISPLAY PROC EAR 期数值转换成ASCII码字符子程序,然后返回dos界面显示出来,然后再循环以同样方法读取月,日。
(3)TIMEDISPLAY PROC EAR子程序
本子程序是显示时间子程序,当键盘输入字母“T”时所调用执行的子程序;通过调用CALL TIMEDISPLAY将时间数值转换成ASCII码字符,因此需调用TIMEDISPLAY PROC NEAR时间数值转换成ASCII码字符子程序,然后返回dos完成一个时间项的显示,然后再循环去读取其他时间项,最后返回主程序执行主程序。
三、详细设计
调用dos系统3号功能设计一个文本区,调用INT 10H显示出来。定义行属性和光标的位置,设置内存空间大小,输入作者信息和提示内容,定义内容地址位置。
WELCOME DB '|*******************WELCOME YOU TO COME HERE!*******************|$' ;提示界面 欢迎你来到这里
INF00 DB 0DH, 0AH,'|*THIS IS A DISPLAY PROGAME!*|$' ;这是一个显示日期时间的游戏,0DH换行,0AH回车
INF01 DB 0DH, 0AH,'|*PRODUCED BY SHANG!*|$' ;由Ever、殇制作
INF02 DB 0DH, 0AH,'|*PLEASE INPUT"D" "T"OR "Q"TO SHOW DATATIME OR EXIT!*|$' ;请在显示数据或退出输入D,T或者Q
INF03 DB 0DH,0AH,'|*D:DISPLAY SYSTEM DATE.$' ;显示系统日期
INF04 DB 0DH,0AH,'|*T:DISPLAY SYSTEM TIME.$' ;显示系统时间
INF05 DB 0DH,0AH,'|*Q:QUIT.$' ;退出
INF06 DB 0DH,0AH,'|*PLEASE INPUT THE CHAR:$' ;请输入字符
INPUTER DB 0DH,0AH,'PNPUT ERROR!$' ;字符输入错误
DATEDIS DB'00-00-0000',0AH,'$' ;显示DATE日期,更换日期的格式
TIMEDIS DB'00:00:00' ,0DH, 0AH, 0AH,'$' ;显示TIME时间
调用dox系统9号功能显示信息提示,在显示信息提示下输入一个字符,再通过调用INT 21H中断的功能,读取键盘输入的内容,若输入D,则调用显示系统日期年、月、日子程序;若输入T,则调用显示系统时间时、分、秒子程序;若输入Q,则退出程序;若不是相关字符,则显示错误。
INPUT:
MOV AH,01
INT 21H
CMP AL,44H ;与D 比较
JNE L1 ;不相等转到 L1
CALL DATEDISPLAY ;相等调用DATEDISPLAY
JMP EXIT1 ;跳转到exit1地址
L1:
CMP AL,54H ;与T比较
JNE L2 ;不相等转L2
CALL TIMEDISPLAY ;相等调用TIMEDISPLAY
JMP EXIT1
L2:
CMP AL,51H ;与Q比较
JE EXIT ;相等转到EXIT,退出
SHOW INPUTER ;显示输入错误
SHOW INF06 ;显示输入提示
JMP INPUT
EXIT1:
SHOW INF06 ;显示输入提示
JMP INPUT
EXIT: MOV AH,4CH ;结束
INT 21H
DATEDISPLAY PROC NEAR显示系统日期子程序
本子程序是当键盘输入字母”D“时所调用执行的子程序:由于读取的日期项是十进制代码,因此需调用CALL DATEDISPLAY把转换为ASCII码字符,然后通过调用DATEDISPLAY PROC NEAR日期数值转换成ASCII码字符子程序,然后返回dos界面显示出来,然后再循环以同样的方法读取月、日最后返回主程序执行主程序。
DATEDISPLAY PROC NEAR
LEA DX,INF03
MOV AH,09H ;调用9号功能显示字符串
INT 21H
MOV AH, 04H
INT 1AH
TIMEDISPLAY PROC NEAR显示系统时间子程序
本子程序是当键盘输入字母”T“时所调用执行的子程序:由于读取的时间项是十进制代码,因此需调用CALL TIMEDISPLAY把转换为ASCII码字符,然后通过调用TIMEDISPLAY PROC NEAR日期数值转换成ASCII码字符子程序,然后返回dos界面显示出来,然后再循环以同样的方法读取分、秒最后返回程序执行主程序。
TIMEDISPLAY PROC NEAR
LEA DX, INF04
MOV AH, 09H ;调用9号功能显示字符串
INT 21H
MOV AH, 02H
INT 1AH
四、源程序代码及运行结果
CLEAR_SCREEN MACRO OP1,OP2,OP3,OP4 ;宏定义,设置参数
MOV AH,06H ;功能调用AH=06 屏幕初始化
MOV AL,00H ;清屏
MOV BH,79H ;卷入行属性
MOV CH,OP1 ;左上角行号
MOV CL,OP2 ;左上角列号
MOV DH,OP3 ;右上角行号
MOV DL,OP4 ;右上角列号
INT 10H ;调用BIOS中断INT 10h,实现指定区域清屏。
MOV AH,02H ;制定光标位置
MOV BH,00H ;第0页
MOV DH,00H ;第0行
MOV DL,00H ;第0列
INT 10H
ENDM
STACK SEGMENT STACK ;定义堆栈段
DB 200 DUP (0) ;重复定义200次字节0,定义一个字节型变量,该变量占用200个字节,所有字节被初始化成0
STACK ENDS
DATA SEGMENT ;定义数据段
WELCOME DB '|*******************WELCOME YOU TO COME HERE!*******************|$' ;提示界面 欢迎你来到这里
INF00 DB 0DH, 0AH,'|*THIS IS A DISPLAY PROGAME!*|$' ;这是一个显示日期时间的游戏,0DH换行,0AH回车
INF01 DB 0DH, 0AH,'|*PRODUCED BY ZHAOXIN!*|$' ;由赵鑫制作
INF02 DB 0DH, 0AH,'|*PLEASE INPUT"D" "T"OR "Q"TO SHOW DATATIME OR EXIT!*|$' ;请在显示数据或退出输入D,T或者Q
INF03 DB 0DH,0AH,'|*D:DISPLAY SYSTEM DATE.$' ;显示系统日期
INF04 DB 0DH,0AH,'|*T:DISPLAY SYSTEM TIME.$' ;显示系统时间
INF05 DB 0DH,0AH,'|*Q:QUIT.$' ;退出
INF06 DB 0DH,0AH,'|*PLEASE INPUT THE CHAR:$' ;请输入字符
INPUTER DB 0DH,0AH,'PNPUT ERROR!$' ;字符输入错误
DATEDIS DB'00-00-0000',0AH,'$' ;显示DATE日期,更换日期的格式
TIMEDIS DB'00:00:00' ,0DH, 0AH, 0AH,'$' ;显示TIME时间
DATA ENDS
CODE SEGMENT ;代码段定义
ASSUME CS:CODE,DS:DATA,SS:STACK ;主程序
MAIN PROC FAR ;系统把主程序当作DOS调用的一个子程序,DOS内核与主程序不是在同一个段地址内
START:
MOV AH,00H ;bios调用,设置显示模式
MOV AL,03H ;设置40*25图形显示
INT 10H
MOV AX, DATA ;将data段的段地址赋予ax
MOV DS, AX ;通过ax将data段地址赋予ds
MOV AX, STACK ;将stack段的段地址赋予ax
MOV SS, AX ;通过ax将stack段地址赋予ss
;*********显示宏定义**********
SHOW MACRO b
LEA DX,b ;取出b首地址到dx中
MOV AH,9 ;用9号dos系统功能调用显示b内容
INT 21H
ENDM
SHOW WELCOME ;显示数据段落的内容
SHOW INF00
SHOW INF01
SHOW INF02
SHOW INF03
SHOW INF04
SHOW INF05
SHOW INF06
INPUT:
MOV AH,01 ;从键盘上输入一个字符,将其对应字符的ASCII码送入AL中,并在屏幕上显示该字符。
int 21H
CMP AL,44H ;与D 比较
JNE L1 ;不相等转到 L1
CALL DATEDISPLAY ;相等调用DATEDISPLAY
JMP EXIT1 ;跳转到exit1地址
L1:
CMP AL,54H ;与T比较
JNE L2 ;不相等转L2
CALL TIMEDISPLAY ;相等调用TIMEDISPLAY
JMP EXIT1
L2:
CMP AL,51H ;与Q比较
JE EXIT ;相等转到EXIT,退出
SHOW INPUTER ;显示输入错误
SHOW INF06 ;显示输入提示
JMP INPUT
EXIT1:
SHOW INF06 ;显示输入提示
JMP INPUT
EXIT: MOV AH,4CH ;结束
INT 21H
MAIN ENDP
;***********日期显示子程序************
DATEDISPLAY PROC NEAR
LEA DX,INF03 ;将NF03的偏移地址放到DX中,使DX指向INF03
MOV AH,09H ;调用9号功能显示字符串
INT 21H
MOV AH, 04H ;调用bios (基本输入输出系统)1A 中段读取系统日期,写入数据区
INT 1AH ;CH=BCD码格式的世纪
;CL=BCD码格式的年
;DH=BCD码格式的月
;DL=BCD码格式的日
;CF=0时钟在走,否则,时钟停止
MOV AX, CX ;设置年并覆盖00/00/0000中的0000
MOV CX,4 ;需要循环4次,把年的4位中每一位取出,并覆盖掉DATEDIS中的后四位字符
LEA SI,DATEDIS+6 ;将si指向年份的第一位
LA1:
PUSH CX ;cx入栈,将年保存
MOV CL, 4
ROL AX, CL ;循环左移4次
MOV BL, AL
AND BL, 0FH ;与运算赋予BL
OR BL, 30H ;或运算赋予BL
MOV [SI], BL ;将BL赋予si地址当中
INC SI ;si自加一,有效地址后移一位
POP CX ;cx出栈
LOOP LA1 ;循环LA1
MOV AX, DX ;设置年并覆盖00-00-0000中的00-00
MOV CX, 4 ;把的4位中每一位取出,并覆盖掉DATEDIS中的第1.2.4.5位字符
LEA SI, DATEDIS ;使si指向datedis
LA2:
PUSH CX ;将cx入栈,保存
MOV CL,4
ROL AX,CL
MOV BL, AL
AND BL,0FH
OR BL,30H
MOV [SI], BL
INC SI
POP CX
CMP CX,3
JNZ P2 ;跳过00-00中的'-'
INC SI
P2:
LOOP LA2 ;循环LA2
LEA DX, DATEDIS ;将日期的有效地址放入dx寄存器
MOV AH, 09H
INT 21H
RET ;调用显示后返回
DATEDISPLAY ENDP
;*********时间显示子程序**********
TIMEDISPLAY PROC NEAR
LEA DX, INF04 ;将INF04的偏移地址放到DX中,使DX指向INF04
MOV AH, 09H ;调用9号功能显示字符串
INT 21H
MOV AH, 02H ;调用bios 1A中断的二号功能获取系统时间,时间计数器当前值写入数据区
INT 1AH ;CH=BCD码格式的小时
;CL =BCD码格式的分钟
;DH =BCD码格式的秒
;DL=OOH标准时间,否则,夏令时
;0r=0时钟在走,否则,时钟停止
MOV AX, CX
MOV CX, 4 ;设置小时,分钟,并覆盖00: 00:00中时分
LEA SI, TIMEDIS
LA3:
PUSH CX
MOV CL, 4
ROL AX, CL
MOV BL, AL
AND BL,0FH
OR BL,30H
MOV [SI], BL
INC SI
POP CX
CMP CX,3
JNZ P3 ;跳过“:”
INC SI
P3:
LOOP LA3
PUSH DX
MOV CL, 4
SHR DH, CL ;DH右移4
OR DH, 30H
MOV TIMEDIS+6, DH ;将DH传送到DIMEDIS+6
POP DX
AND DH, 0FH
OR DH, 30H
MOV TIMEDIS+7, DH
LEA DX, TIMEDIS ;显示时间
MOV AH, 09H
INT 21H
RET ;时间调用后返回
TIMEDISPLAY ENDP
CODE ENDS
END START
运行结果:
五、总结
经过不懈的努力,我们完成了程序设计。
虽然本次课程设计中所需要的知识在平时课程中没有涉及到,但是汇编的根,基还是我们在课堂上所掌握的基本知识,这使我认识到平时基础知识的重要性,只有能够熟练的掌握才能在实验过程中得心应手,否则一步错则整个试验都会陷入困境,因而,严谨的态度是试验成功的重要保障;其次,通过这次课程设计,我对各个函数以及语句有了进一步的了解,对各个语句的功能有了更深刻的认识和体会,特别是掌握了大量的DOS调用及程序设计的基本方法;最后,在课程设计过程中,同组人员之间相互合作,共同研究使我更加坚信了团体的力量。
感谢老师和学长的支持和帮助!