汇编语言课程设计电子闹钟.docx
《汇编语言课程设计电子闹钟.docx》由会员分享,可在线阅读,更多相关《汇编语言课程设计电子闹钟.docx(19页珍藏版)》请在冰豆网上搜索。
![汇编语言课程设计电子闹钟.docx](https://file1.bdocx.com/fileroot1/2022-11/30/097eb719-212e-4d1d-a942-7a30b2e246b1/097eb719-212e-4d1d-a942-7a30b2e246b11.gif)
汇编语言课程设计电子闹钟
电子闹钟
一、课题内容和要求
题目描述:
利用汇编语言实现一个可以在显示器上显示时、分、秒的电子时钟,并能提供整点报时功能。
基本要求:
(1)设计一个基本的具有显示时、分、秒的电子时钟。
(2)到整点或预定的报警时间,能够以不同的音乐进行报时,可以自行设置闹钟报警时间;
(3)实物演示时要求讲出程序原理和设计思想;
(4)程序运行良好、界面清晰。
提高要求:
设计一个具有钟面、分针、秒针的指针式钟表,在圆盘上有均匀分布的60根刻度,对应小时的刻度用不同颜色的长刻度区别,并且将12、3、6、9对应的拉丁文绘制于表盘外。
设计提示:
(1)指针式钟表的绘制。
将屏幕设置成图形显示方式,通过画点、画线,画圆等基本程序完成钟表的绘制。
表盘圆周上刻度线段两端点坐标计算是钟表绘制的核心部分。
(2)秒针、分针、时针的转动。
是经过一定的延时时间,通过在下一位置重新画一个,在原来的位置用背景色覆盖的方法实现。
(3)音乐的演奏。
利用CPU支持的外围电路8254与8255,通过汇编程序改变8255的PB0,PB1口,接通扬声器,使得计算机能够发出一定频率的声音,同时通过8254的与8255连接的2号计数器控制指定频率,从而达到控制扬声器的音乐的效果。
通过建立适当的延时程序达到一定时间后则改变2号计数器产生的方波的频率,实现音乐程序的演奏。
二、需求和思路分析
经分析本次程序设计的主要内容主要分为如下的几个模块:
当前时间的获取并显示,码制转换,设定闹钟报鸣的时间,不同频率的闹铃声,钟表的绘制和并实现动态等模块。
其中钟表的绘制和动态走动部分比较难是本次课程设计的提高部分,且改模块可单独形成一个模块,所以放到最后进行考虑
1时间的获取可以用int21h的2ch功能,该功能调用DOS时间调用功能,功能号:
2cH,小时,分钟,秒数分别保存在,保存的形式是以二进制的形式,故显示时要
2码制转化利用ascii码与二进制码的关系ascii=二进制+30H
3闹钟鸣叫主要利用8254的二号计数器和8255的PB0和PB1来设定
4闹钟的表盘,指针的绘制,并实现时针,分针,秒针的走动。
主要通过过图形的画点进行操作,并通过在固定的区域内不断的刷屏来实现。
三、概要设计
(一)算法设计及重要程序流程图
1)程序整体流程
2)edittime子程序流程图
2)editmusic子程序
3)打开和关闭扬声器
此处重要用到了8254和8255的相关知识,书中P238有相关代码
首先,应该读出8255的PB端口当前的状态,将PB0和PB1分别置1,以读修改写的方式修改PB0和PB1接通扬声器。
其次,利用8254的2号计数器产生XXXHz的方波,此处计数初值利用公式
N=fclk1/fout2
对8254先写低8位,再写高8位,out2输出方波
最后,将8255的PB0和PB1回复位00,用ANDAL,11111100B来修改
4)bctd子程序的流程图
该子程序程序功能主要是实现二进制转化成相应BCD码
AX输入参数
AX输出参数,存放调整过的BCD码
(二)变量名声明
datasegment
mess1db'****************ASMASSIGNMENT****************',0ah,0dh
db'',0ah,0dh
db'***************ELECTRONICCLOCK***************',0ah,0dh
db'',0ah,0dh
db'',0ah,0dh
db'*******PressCorctoeditthealarmtimePressMormtochangesound!
****',0ah,0dh
db'',0ah,0dh
db'***********PressESCbuttontoexit***********',0ah,0dh,'$'
tndb'Pleaseinputthenewtime(hh:
mm:
ss):
',0dh,0ah,'$'
musicmessdb'Pleasechoosethetypeofmusic:
1(fast)2(middle)3(slow)',0dh,0ah,'$'
mess2db'*******Timeis:
',0ah,0dh,'$'
t_buffdb40;在数据段开一段时间显示缓冲区
db?
db40dup(?
)
temphordb?
;存放键入的定时时间的小时
tempmindb?
;存放键入的定时时间的分钟
tempsecdb?
;存放键入的定时时间的秒数
musicdw800;存放默认音乐的频率数
dataends
stacksegment
db100dup(?
)
stackends
四、详细设计
课题任务实现的源程序(可以是一组源程序,每个功能模块采用不同的函数实现),源程序要按照写程序的规则来编写。
要结构清晰,重点函数的重点变量,重点功能部分要加上清晰的程序注释。
(一)
1主函数代码
codesegment
assumecs:
code,ss:
stack,ds:
data;确定各个逻辑段的类型
start:
movax,data
movds,ax
callclear;调用清屏子程序
display:
;时间显示部分
movax,data
movds,ax
movbx,offsett_buff;送t_buff的偏移地址到BX
movah,2ch;调用DOS时间调用功能,功能号:
2cH,小时,分钟,秒数分别保存在CH,CL,DH中
int21h;判断时间是否相等
subdh,1;秒钟+1修正
CALLCHECK
moval,ch;小时数设定
movah,0
callbctd;调用进制转换子程序二进制转BCD码子程序
pushax
andal,0f0h;选取al高四位
movcl,4;设置右循环的次数
rolal,cl;右循环
oral,30h;加30h得到ACSII码
mov[bx],al;将得到的结果送到t_buff缓冲区
incbx;BX自加1,指针指向下一个缓冲区的下一个地址
popax
andal,0fh;选取低四位
oral,30h
mov[bx],al;将转换后的低四位值送入缓冲区的第二个地址
incbx
;----------------------------------------------------------
moval,':
';显示分隔符号
mov[bx],al
incbx
;-------------------------------------------------------
movah,2ch
int21h
moval,cl;分钟数设定
movah,0
callbctd
pushax
andal,0f0h
movcl,4
rolal,cl
oral,30h
mov[bx],al
incbx
popax
andal,0fh
oral,30h
mov[bx],al
incbx
;-------------------------------------------------------------------------
moval,':
';显示分隔符号
mov[bx],al
incbx
;-------------------------------------------------------------------------
movah,2ch;秒设定
int21h
moval,dh
movah,0
callbctd
pushax
andal,0f0h
movcl,4
rolal,cl
oral,30h
mov[bx],al
incbx
popax
andal,0fh
oral,30h
mov[bx],al
incbx
;----------------------------------------------------------------------
moval,'$';将字符串的结束位送至显示缓冲区的最后一位
mov[bx],al
;------------------------------------------------------------------------
pushbx;置光标位置,AH=2,BH=0,DH跟DL分别为行号与列号,并入栈保护BX
movah,2;0~1用于此程序快下边的在下面的两个置光标位置
movbh,0
movdh,17
movdl,41
int10h
popbx
leadx,t_buff;送t_buff偏移地址到DX,并调用DOS显示功能,功能号为9
movah,9
int21h;至此当前事前时间的显示功能结束!
pushbx;置光标位置
movah,2
movbh,0
movdh,0
movdl,0
int10h
popbx
leadx,mess1
movah,9
int21h;显示mess1
pushbx;置光标位置
movah,2
movbh,0
movdh,17
movdl,21
int10h
popbx
leadx,mess2
movah,9
int21h;显示mess2
;-----------------------------
calldelay1
movah,1;调用键盘I/O中断功能号1,获取键值到AL
int16h
cmpal,'c';是c键,转到时间修改程序
jeedittime
cmpal,'C';是C键,转到时间修改程序
jeedittime
cmpal,'m';是m键,转到闹铃种类设定程序
jeeditmusic
cmpal,'M';是M键,转到闹铃种类设定程序
jeeditmusic
cmpal,1bh
jzquit;是ESC键,退出程序
jmpdisplay
quit:
movah,4ch;程序终止功能号
int21h
ret
2功能函数代码
1)二进制转BCD码子程序
bctdprocnear;二进制转BCD码子程序
;AX输入参数
;AX输出参数,存放调整过的BCD码
movdx,ax
movax,0
movcx,16;设循环次数
bctd1:
clc;清进位标志C
rcldx,1;通过进位的循环右移
adcal,al;带进位加法
daa;加法的十进制调整
xchgal,ah;交换高、低八位
adcal,al
daa
xchgal,ah
loopbctd1;循环次数保存在CX里
ret
bctdendp
2)清屏clear子程序
clearprocnear
pushax;入栈保护现场
pushbx
pushcx
pushdx
movax,0600h;ah=06(滚动)al=00(全屏空白)
movbh,3eh;设置背景颜色
(2)和前景颜色(e)
subcx,cx
movdx,5f5fh
int10h
popdx;出栈恢复现场
popcx
popbx
popax
ret
clearendp
3)精确延迟时间子程序delay1
delay1PROC;精确延迟时间子程序
MOVDX,04ffh;循环次数
up:
XORCX,CX
a:
NOP
LOOPa
DECDX
JNZup
RET
delay1ENDP
4)设定定时时钟edittime子程序
edittimeproc;时间修改子程序
pushax;入栈保护数据
pushbx
pushcx
pushdx
pushf
movdx,offsettn;显示修改时间的格式提示
movah,09h
int21h
movdx,offsett_buff;数据缓冲区的数据输入
movah,0ah
int21h
anddx,0h
leabx,t_buff
incbx
incbx
incbx
movdh,[bx]
subdh,30h
incbx
movdl,[bx]
subdl,30h
movcl,10
moval,dh
mulcl
addal,dl
movch,al
movtemphor,al
incbx
incbx
movdh,[bx]
subdh,30h
incbx
movdl,[bx]
subdl,30h
movcl,10
moval,dh
mulcl
addal,dl
movcl,al
movtempmin,al
incbx
incbx
movdh,[bx]
subdh,30h
incbx
movdl,[bx]
subdl,30h
movcl,10
moval,dh
mulcl
addal,dl
movdh,al
movtempsec,al
popf;出栈恢复数据
popdx
popcx
popbx
popax
jmpstart
ret
edittimeendp
5)检验定时时间是否到CHECK子程序
CHECKPROC
pushax
pushbx
cmpch,temphor;设置定点报时
jnecf
cmpcl,tempmin
jnecf
cmpdh,tempsec
jnexiang
cf1
cmpcl,0;设置整点报时
jnecf
cmpdh,0
jnecf
xiang:
CALLOPEN;打开扬声器
PUSHDX
PUSHCX
MOVDX,12H
MOVAX,34DEH
movcx,music
DIVCX
OUT42H,AL
MOVAL,AH
OUT42H,AL
MOVAH,1
INT21H
POPCX
POPDX
CALLCLOSE;关闭扬声器
CF:
popbx
POPAX
RET
CHECKENDP
6)开启和关闭扬声器子程序open和close
OPENPROC
PUSHAX
INAL,61H
ORAL,03H
OUT61H,AL
POPAX
RET
OPENENDP
CLOSEPROC
PUSHAX
INAL,61H
ANDAL,0FCH
OUT61H,AL
POPAX
RET
CLOSEENDP
6)设置闹钟音乐种类子程序editmusic
Editmusicproc
pushax;入栈保护数据
pushbx
pushcx
pushdx
pushf
movdx,offsetmusicmess;显示修改音乐的种类提示
movah,09h
int21h
movdx,offsett_buff;数据缓冲区的数据输入
movah,0ah
int21h
anddx,0h
leabx,t_buff
incbx
incbx
incbx
moval,[bx]
cmpal,'1'
jem800to
cmpal,'2'
jem1600to
cmpal,'3'
jem3200to
m800to:
movmusic,800
jmpt
m1600to:
movmusic,1600
jmpt
m3200to:
movmusic,3200
t:
popf;出栈恢复数据
popdx
popcx
popbx
popax
jmpstart
ret
Editmusicendp
五、测试数据及其结果分析
1)运行画面
2)测试结果
A)键入c或C
会出现提示“Pleaseinputthenewtime(hh:
mm:
ss):
”
再输入19:
08:
40。
回车结束后,在19:
08:
40时,闹钟会鸣叫。
B)键入m或M
会出现提示“Pleasechoosethetypeofmusic:
1(fast)2(middle)3(slow):
”
回车后会设定此时的闹铃鸣叫的频率
六、调试过程中的问题
本次程序设计中遇到了很多的问题,在设计每一个模块都有遇到了一定的难度。
首先关于,如何获得系统当前的时间,查阅了INT21H,21H的2ch可以返回的的CH,CL,DH中分别为时,分,秒但是都是二进制的,故需要的进行二进制的码制,写代码时发现通过寄存器移位的可以十分的节省寄存器的使用数目。
其次在写edittime的子程序是发生了一个错误,很久才改正。
我在使用21H的0AH向t_buffer内存空间输入字符串是,第一个位置是初始化时设定的t_buffer的最大长度,第二个位置是实际输入的长度,我于是incbx两次(BX发的t_buffer的地址),以为能够得到我的输入的第一个字符,但是结果是错误的,查了了很久才发现,其实我在调用该子程序前的一个控制已经输入了一个字符,该字符已经存入了t_buffer,故此处应该在incbx。
在editmusic的子程序中同样会遇到类似问题。
在编写程序中由于经常的要使用寄存器,有时没有将其压栈保存,导致寄存器的值发生了不可知的变化。
所以一定要注意压栈的使用
在实验中使用masm开发环境,因为开始发现未来汇编的jne等功能的转移范围有限制,但是在masm中转移的范围很大。
本程序并没有对一些异常输入和其他的异常进行处理,所以在程序的健壮性上有所欠缺。
后来一直在看关于绘制钟表的相关代码,看懂了一半,但是还是没能完成,希望以后有机会能够完成
七、专业课程设计总结
通过本次的课程设计,对汇编语言和微型计算机接口计数,有了更加深刻认识,复习了关于8254和8255的相关知识。
自己设计了程序的全部的流程,对每个环节都要十分清楚。
代码完成后深切的感觉到,编写代码前的设计十分的重要。
因为,如果等到完成了许多功能后,再需要增添一个功能,或改写一个光标的位置,汇编语言的改写比java等高级语言麻烦的多,十分不好改,毕竟汇编是一种低级语言,没有面向对象的概念,很有可能大部分带都重写,导致效率十分低。
在程序的调试过程中熟悉了通过观察各个寄存器内值的变化来跟踪程序的运行是否有误。
在编写程序的时候发现许多的技巧比如要学会多利用左移或右移的操作,这样会十分的节省寄存器的使用。
另外当你的寄存器不够时,可以先把几个寄存器压栈,进行操作后在弹出栈,这样可以解决寄存器不够,或某些寄存器的值不知觉的被改变。
总之这次的汇编实验比JAVA那部分要难一点,还好最后把基本功能完成了,能够实现一个电子闹钟的定时,整点鸣叫,设定闹钟铃声的种类。
自己第一次编写这么多的汇编的代码。
唯一有点遗憾的地方是,提高的钟表指针走动的功能没能够实现,网上找到一个范例,但是只看懂了一半,只看懂了绘制的过程,对指针如何走动还是没弄懂,希望以后有机会,能够对无论是汇编的图形绘制还是其他高级语言的图形绘制再次实践一下。
充分的锻炼自己!