微机原理多功能程序的设计.docx
《微机原理多功能程序的设计.docx》由会员分享,可在线阅读,更多相关《微机原理多功能程序的设计.docx(49页珍藏版)》请在冰豆网上搜索。
微机原理多功能程序的设计
福建工程学院
课程设计
专 业:
班 级:
座号:
姓名:
日期:
福建工程学院计算机与信息科学系
实验报告
2011–2012学年第2学期任课老师:
课程名称
微机接口技术
课程设计
班级
计1002
座号
姓名
实验题目
多功能程序的设计
实验时间
实验开始日期:
2012.6.14
报告提交日期:
2012.6.20
设计目的、要求
设计目的:
1.加深对课程理论知识的理解;
2.通过编写一定规模和难度的程序,进行一次较全面的汇编编程训练,提高分析问题和解决问题的能力;提高调试程序的能力。
3.熟悉和掌握微机系统的软件、硬件设计的方法、设计步骤,作为微机开发应用方面的初步训练。
设计要求:
1.设置一个主菜单界面,通过按键选择进入以下其中一项功能(按键自己设置,可以是数字键或字母),按ESC返回主菜单;按Q键退出系统;要求界面简洁明了,易于操作。
2.时间显示功能。
在屏幕上以hh:
mm:
ss的格式显示系统时间、并以一定时间间隔随机改变显示位置;
3.日期显示功能。
在屏幕上以yyyy-mm-dd的格式显示系统日期、并以一定时间间隔随机改变显示位置;
4.闰年判断功能。
提示输入闰年,对输入内容具有容错处理,计算是否闰年,然后输出结果;
5.代码转换功能。
实现不同数制的输入并转换成另一种数制输出,如将十进制数转换为其对应的二进制数、将二进制数转换为其对应的十进制数、将十进制数转换为其对应的十六进制数、将十六进制数转换为其对应的十进制数等。
选一种或多种转换实现;
6.音乐播放功能。
利用计算机中的8253控制扬声器发音来实现;能选择多首乐曲中的一首演奏,乐曲自选;定义14个键,对应低音区和中音的1—7,模仿电子琴能随意演奏乐曲;
实验步骤与内容
按如下顺序写:
1、主要设计思想;
时间显示模块:
通过BIOS功能调用读取当前日期年、月、日和系统时钟时、分、秒数据,再转化为相应数字字符的ASCII码存放于内存缓冲区,再调用BIOS功能显示内存缓冲区的内容,为显示停留一段时间,需要延时,时长为近似一秒。
如此过程反复、循环实现时间的显示。
为显示能改变位置的目的,需改变显示位置的参数,通过产生随机数0-59送横坐标,0-24送纵坐标来改变时间显示的位置
闰年的判断模块:
输入前将YEAR单元清零,通过DOSAH01H,INT21H功能从键盘输入年份字符,检查输入的是否为数字字符,如果不是则提示输入错误;如果是,则将其ASCII码减30H转化为数字(对应的BCD码)暂存入NUM中,将YEAR中的数值乘以10再加上NUM,这样就完成一个字符的输入,重复读取字符直到遇到回车或数值位数达到4位,这样得到的包括年份的千位、百位、十位、个位,之后转化为数字的年份做被除数去除4、100、400判断是否为闰年或者平年,并调用DOS09号功能显示判断结果。
进制转换模块:
实现十进制转二进制、十六进制,二进制转十进制,十六进制转十进制。
十进制转二进制:
读入字符,判断是否为合法字符(0~9),将字符转BCD码,再以二进制形式存入DX中,继续读入字符,先将DX中的内容乘以10再加上新的字符的二进制值,直到回车符,读取完毕。
将DX中的内容送BX(显示字符串要用DX)将BX循环左移(根据循环左移指令ROLdst,1/CL的功能:
将dst中的二进制位向左移动1位或CL中指定的位数。
左移一位时操作数的最高位移出送到CF中同时送到最低位)如果CF为零则输出字符零如果CF为一则输出字符1,这样就完成了二进制的输出。
二进制转十进制:
DX清零(用以存放输入的二进制数),读入字符,判断是否为合法字符(0、1)不是则报错;将字符转换为对应的BCD码,判断输入的是0还是1,如果是0则DX左移一位,如果是1则DX左移一位并加1,重复读入字符直到遇回车符。
将DX中的内容送BX,DX清零用于存放余数。
将BX除以10得余数送DL中,再加上30H得到对应的ASCII码存入PTR1开始的第SI个单元如此重复就可以将转换的十进制数存入PTR1中,再加PTR1的内容显示出来即可。
十进制转十六进制:
输入遇十进制转二进制一致,将对应的二进制存放在BX中,DL循环左移四位,把要输出的内容放在低4位的DL中,将高4位清零。
DL中的内容与10比较,小于10的数字不变将其加上30H转换为对应的ASCII码输出对应字符,大于10的将数值加07H调整使10~15的字符变为A~F,输出对应的字符即可。
重复上述输出即完成了转换。
十六进制转十进制:
DX清零(用以存放输入的十六进制数),读入字符判断是否为(0~9)是的话直接减30H转为对应的BCD码,如果是(A~F)则减37H转为对应的BCD码,对应的二进制存入DX中,如果再读入字符则DX算术左移4位(即DX乘以16)再加上对应的字符二进制。
将DX中的内容送BX,DX清零用于存放余数。
将BX除以10得余数送DL中,再加上30H得到对应的ASCII码存入PTR2开始的第SI个单元如此重复就可以将转换的十进制数存入PTR2中,再加PTR2的内容显示出来即可。
2、模块划分
读取系统时间模块
产随机数模块
时间显示模块显示模块
延迟模块
清屏模块
闰年的判断模块转换模块
十进制转二进制模块
检查合法字符模块
转换模块
十进制转十六进制模块
检查合法字符模块
进制转换模块
转换模块
二进制转十进制模块
检查合法字符模块
转换模块
十六进制转十进制模块
检查合法字符模块
3、程序源代码及注释;
见ASM文件,ASM文件名为学号太长了不能直接编译连接
程序的流程框图:
所有使用的DOS/BIOS功能调用:
从键盘读入字符
调试过程
时间显示模块:
开始时读取系统当前时间后显示,显示出的时间是正确的,但是后面会出现‘....’如图
,有时候是一整屏。
解决方法
INT1AH;读取当前时间;出口参数:
CX=时/分;DH=秒
MOVAL,CH;显示时
CALLDISP
MOVAH,09H;绿色
MOVBL,0AH
MOVBH,0
MOVCX,1
INT10H
需将CX置1,但是读取的系统时间时、分存放在CX中,时已经显示出来但是分未显示,所以显示分的时候重新读取一下系统时间。
要不会出现
这样的错误。
MOVAH,02
INT1AH;重新读取当前时间;出口参数:
CX=时/分;DH=秒
MOVAL,CL;显示分
CALLDISP
MOVAH,09H;绿色
MOVBL,0AH
MOVBH,0
MOVCX,1
INT10H
会出现一半在右边,一半在左边的现象
原因:
DOS窗口长79,宽24,而时间字符串长20故横坐标不应该超过59,纵坐标不该超过24,如果横坐标超过59就会出现上述情况,如果纵坐标超过24则在窗口范围内没有显示出时间。
进制转换模块:
十进制转换二进制时输入的不是数字字符也会运行
解决方法:
添加一个检查字符功能,如果输入的不是0~9、回车符就提示输入错误。
本来以为退格符可以作为合法字符输入但是结果不对(测试时输入1、1、DEL、1)
我的解释是:
输入时是一个字符一个字符读入,前面11是合法字符,而这里的退格符也作为合法字符就又累加上DEL所对应的数值,然后又读入合法字符1,故回显的数值为11,而结果是不正确的,所以把退格符也定义为非法字符。
输入过程中不允许修改之前输入的内容。
问题:
如果要修改的话该怎么实现?
实验结果记录以及与预期结果比较以及分析
记录每次实验结果以及分析情况
菜单:
选择1(时间显示功能:
随机改变显示位置(每秒改变一次))
按ESC回到菜单
选择2(判断闰年)
Y回到菜单
选择4(音乐)
任意键返回主菜单
选择Q(退出)
选择3(进制转换)
按ESC返回主菜单
选择1(十进制转二进制)
Y回到子菜单
选择2(十进制转十六进制)
Y回到子菜单
选择3(二进制转十进制)
Y回到子菜单
选择4(十六进制转十进制)
Y回到子菜单
演示完毕!
!
总结以及心得体会
通过一周的课程设计,使我加深对课程理论知识的理解,对各指令的使用更加熟悉。
所要完成的功能我们用c语言基本上完成过了,但是用汇编语言的确有一定的难度,在数据定义一块中定义菜单的时候还是不知道怎么画出好看的边框,还有怎么让选项居中,我这里是用空格去调整的。
通过这样一周的汇编编程训练,使我对课本知识有一次较全面的复习。
设计中写的函数比较多,实现各个函数间的相互调用等都需要较高的总体把握能力,通过这样的训练,无形中提高了分析问题和解决问题的能力;提高了调试程序的能力。
编程经验:
1、首先,程序必须模块化。
2、每个模块(子程序)执行一个功能。
每个模块只有一个出口。
3、为每个子程序配置一个容易识别的函数名。
4、经常备份代码。
很多时候代码改着改着就不能运行了,而且错误非常多,这时候你备份的代码就派上用场了。
5、接受一个事实,你并不是最牛的程序员。
所以,要向他们学习,不懂要问(前提是尽自己最大的努力去思考问题了)。
6、给予别人帮助。
你或许从未意识到...这样你会使很多人成长,并且在帮助他们的同时你也会学到很多东西,而且你也会感到很开心。
7、给代码加注释,不论是自己调试的时候容易看出问题,问别人问题的时候,别人能很快看懂你的代码,帮你解决问题
程序改进之处:
检查合法字符模块check函数,可以通过给变量赋值,通过判断变量值执行相应的检查操作,这样就不用每个检查都写成一个函数。
同理随机数的产生也可以这样实现。
指导老师评阅意见
指导老师:
年月日
填写内容时,可把表格扩大。
实验的源程序代码(要有注释)附在表后。
STACKSSEGMENTSTACK;堆栈段
DW128DUP(?
);注意这里只有128个字节
STACKSENDS
DATASSEGMENT;数据段
;请在这里定义您的数据
;----------------------------------------------------------------------------------
;定义菜单
;----------------------------------------------------------------------------------
STR1DB'|------------------------------------------------------------------------------|',0DH,0AH
DB'|*1.SHIJIAN|',0DH,0AH
DB'|*2.RUNNIAN|',0DH,0AH
DB'|*3.JINZHI|',0DH,0AH
DB'|*4.YINYUE|',0DH,0AH
DB'|CHOOSE(1-4)TOPLAY!
QTOEXIT|',0DH,0AH
DB'|IFYOUAREPLAYING,YOUCANCHOOSEESCTORETURN!
|',0DH,0AH
DB'|------------------------------------------------------------------------------|',0DH,0AH
DB'PLEASECHOOSE:
'
LENEQU$-STR1;菜单长度
STR2DB'CHANGE',0DH,0AH
DB'|------------------------------------------------------------------------------|',0DH,0AH
DB'|*1.D->B|',0DH,0AH
DB'|*2.D->H|',0DH,0AH
DB'|*3.B->D|',0DH,0AH
DB'|*4.H->D|',0DH,0AH
DB'|------------------------------------------------------------------------------|',0DH,0AH
DB'PLEASECHOOSE:
'
LEN0EQU$-STR2;子菜单长度
;-----------------------------------------------------------------------------------
;定义其他数据
MESSAGE1DB'PLEASEINPUTYOURYEAR:
'
LEN1EQU$-MESSAGE1
MESSAGE2DB'THEYEARYOUENTERISALEAPYEAR!
'
LEN2EQU$-MESSAGE2
MESSAGE3DB'THEYEARYOUENTERISNOTALEAPYEAR!
'
LEN3EQU$-MESSAGE3
MAINBDB'DOYOUWANTTORETURNMAINMENU(Y/N):
'
LENBDW$-MAINB
ERRORDB'ERROR:
PLEASEINPUTINTEGER!
'
LENERROREQU$-ERROR
MESSAGE4DB'(DtoB)PLEASEINPUTTHENUMBERYOUWANTTOTRANSFORM:
'
LEN4EQU$-MESSAGE4
MESSAGE5DB'(DtoH)PLEASEINPUTTHENUMBERYOUWANTTOTRANSFORM:
'
LEN5EQU$-MESSAGE5
MESSAGE6DB'(BtoD)PLEASEINPUTTHENUMBERYOUWANTTOTRANSFORM:
'
LEN6EQU$-MESSAGE6
MESSAGE7DB'(HtoD)PLEASEINPUTTHENUMBERYOUWANTTOTRANSFORM:
'
LEN7EQU$-MESSAGE7
STR3DB'SORRY,THEREISNOMUSICCANBEPLAYEDHEAR!
',0DH,0AH
DB'PRESSANYKEYTORETURNTOMAINMENU......'
LEN8EQU$-STR3
YEARDW0
NUMDB0
TENDB0
HANDB0
THDB0
PROMPT_TWODB0AH,0DH,0AH,0DH,0AH,0DH,'Thebinary:
$'
PROMPT_THRDB0AH,0DH,0AH,0DH,0AH,0DH,'Thedecimal:
$'
PROMPT_FORDB0AH,0DH,0AH,0DH,0AH,0DH,'Theheximal:
$'
STRINGDB?
0DH,0AH,'$';进制转化用
PTR1DB5DUP(?
);进制转化用
PTR2DB5DUP(?
);进制转化用
;-----------------------------------------------------------------------------------
DATASENDS
CODESSEGMENT;代码段
ASSUMECS:
CODES,DS:
DATAS,ES:
DATAS
START:
MOVAX,DATAS;初始化
MOVDS,AX
;----------------------------------------------------------------------------------
;菜单显示模块
;----------------------------------------------------------------------------------
RETURNM:
MOVES,AX
MOVAL,3
MOVAH,0;设置80×25彩色文本方式
INT10H
MOVBP,SEGSTR1
MOVES,BP
MOVBP,OFFSETSTR1;bp指向字符串首地址
MOVCX,LEN;字符串长度给cx
MOVDX,0;设置显示的起始位置
MOVBL,0AH;黑底底绿字
MOVAL,1;设置显示方式
MOVAH,13H;显示字符串
INT10H
MOVAH,3;读取当前光标
INT10H
;----------------------------------------------------------------------------------
;选择操作
;----------------------------------------------------------------------------------
INPUT:
MOVAH,02H;置光标位置
MOVDH,16
MOVDL,15
MOVBH,0
INT10H
MOVAH,1;输入菜单选择
INT21H
CMPAL,'1';选择1显示时间
JNZCHOOSE2
TT:
CALLTIME
MOVAH,01H;检测键盘是否有输入
INT16H
CMPAL,1BH;如果是ESC则返回主菜单
JZRETURNM
JMPTT
CHOOSE2:
CMPAL,'2';选择2判断闰年
JNZCHOOSE3
CALLLEAP
JMPINPUT
CHOOSE3:
CMPAL,'3';选择3进制转换
JNZCHOOSE4
CALLCHANGE
JMPINPUT
CHOOSE4:
CMPAL,'4';选择4音乐播放
JNZCHOOSEQ
CALLMUSIC
JMPINPUT
CHOOSEQ:
CMPAL,'Q'
JZQUIT
JMPINPUT
QUIT:
MOVAX,4C00H;退出程序
INT21H
;----------------------------------------------------------------------------------
;时间显示函数
;----------------------------------------------------------------------------------
TIMEPROC
PUSHAX
PUSHBX
PUSHCX
PUSHDX
MOVAH,00H;置显示方式
MOVAL,03H
INT10H
BEGAIN:
;设置时间显示的位置
CALLRAND1
MOVDL,BL
CALLRAND2
MOVDH,BL
MOVAH,02H;置光标位置
MOVBH,0
INT10H
CALLTIMES
CALLDLY
CALLCLEAR
POPDX
POPCX
POPBX
POPAX
RET
TIMEENDP
;-------------------------------------------------------------------------------
;产生随机数送dl
;--------------------------------------------------------------------------------
RAND1PROC
PUSHCX
PUSHDX
PUSHAX
STI
MOVAH,0;读时钟计数器值
INT1AH
MOVAX,DX;清高6位
ANDAH,3
MOVDL,60;除60,产生0~59余数
DIVDL
MOVBL,AH;余数存BX,作随机数
POPAX
POPDX
POPCX
RET
RAND1ENDP
;----------------------------------------------------------------------------
;产生随机数送dh
;----------------------------------------------------------------------------
RAND2PROC
PUSHCX
PUSHDX
PUSHAX
STI
;MOVAH,0;读时钟计数器值
;INT1AH
MOVAX,DX;清高6位
ANDAH,3
MOVDL,25;除24,产生0~24余数
DIVDL
MOVBL,AH;余数存BX,作随机数
POPAX
POPDX
POPCX
RET
RAND2ENDP
;----------------------------------------------------------------------------------
;获取时间并完成显示函数
;----------------------------------------------------------------------------------
TIMESPROC
PUSHAX
PUSHBX
PUSHCX
PUSHDX
MOVAH,04
INT1AH;读取日期;出口参数:
CX保存年,DX保存月/日
MOVAL,CH;显示年
CALLDISP
MOVAL,CL
CALLDISP
MOVAH,09H;绿色
MOVBL,0AH
MOVBH,0
MOVCX,1
INT10H
MOVAH,0EH;显示字符
MOVAL,'-';字符
MOVBL,0AH
MOVBH,0
INT10H
MOVAL,DH;显示月
CALLDISP
MOVAH,09H;绿色
MOVBL,0AH
MOVBH,0
MOVCX,1
INT10H
MOVAH,0EH;显示字符
MOVAL,'-';字符
MOVBL,0AH
MOVBH,0
INT10H
MOVAL,D