模拟老虎机汇编程序课程设计报告+代码.docx
《模拟老虎机汇编程序课程设计报告+代码.docx》由会员分享,可在线阅读,更多相关《模拟老虎机汇编程序课程设计报告+代码.docx(22页珍藏版)》请在冰豆网上搜索。
模拟老虎机汇编程序课程设计报告+代码
微机原理课程设计报告
模拟实现老虎机游戏
__
__
__
一.设计任务及要求
1.任务:
模拟实现老虎机游戏。
2.要求:
老虎机的游戏规则规定如下:
Ø每个滚筒上有7个数字1~7,三个滚筒在启动老虎机后开始旋转,经过一段时间后滚筒静止,根据静止时的数字确定输赢。
Ø大小比较为:
3个7>3个6>……>3个1>567>456>345>234>123,赔率情况可以由自己确定。
Ø通过按某键模拟老虎机的启动、旋转。
Ø通过按某键可停止老虎机旋转。
Ø通过按某键可正常退出模拟程序。
Ø有较完整的程序运行界面。
二.题目分析
该题目主要是实现模拟老虎机的效果,这个题目对我来说是一个有趣的题目,可以在游戏中的去完成任务,让我有更多的动力去做这个事情。
首先,虽然要求中对老虎机玩法有简单的介绍,但为了更好的完成任务,我需要查找资料去了解老虎机更多的信息,根据题目要求,我首先需要打印一些欢迎信息和提示信息,布置友好的界面,当用户按下"R"键时,老虎机滚筒开始旋转,直到按下"S"时滚筒停止,然后判断滚筒停止后的三个数字来决定玩家的奖金,根据大小,三个7,三个6……,123的奖金分别为12倍,11倍……1倍,然后打印获奖信息。
用户可以重复按下"R"和"S"来进行娱乐,直到按下"E"之后,游戏退出。
三.设计思路
为了实现要求的功能,本设计可以用模块化设计,产生随机数程序和延时程序可以作为一个函数来实现,像有些功能需要传递参数的,我可以用宏来实现,比如说设置光标位置,设置字符颜色等,用这些模块来设计可以减少代码量,同时也使程序变得简单,可读性大大增强。
我的思路是这样的,程序首先输出玩法的信息,告诉玩家应该按哪些键进行操作。
然后等待玩家的输入,当玩家按下开始玩的键后,老虎机滚筒开始旋转,旋转过程的实际上就是产生三个随机数,并存放在定义了三个字符的NUM中,旋转的速度通过延时子程序来决定,通过设置延时子程序中的参数来决定延时的长久,然后隔一些时间,玩家按下停止键后,滚筒静止,比较NUM和有奖金的数字,如果玩家中奖,打印恭喜玩家的语句并显示赢的数量,否则告诉玩家失败。
四.方案设计
1.程序主框架
图1.程序主框架
如图1所示,这个框架主要是实现了设计思路的构造,程序刚开始需要清屏,因为masm5运行之前屏幕中有其它的字符,所以首先要清除这些不必要的字符,以免影响界面的美观性。
清屏之后首先打印欢迎信息和操作方法,此时,一切就绪,等待玩家的输入,根据玩家的按键进行操作,操作流程在设计思路中已讲述,此处不再介绍
2.滚筒工作流程
图2.滚筒工作流程
滚筒工作流程如图2所示,程序是在用户按"R"键后进入的,开始的时候,清除上次玩家运行的结果,比如清除上次玩家的中奖信息,然后产生第一个随机数,显示在三个滚筒位置的最左边,同时存放在NUM的第一个字符位置,在数段中,定义了:
NUMDB''
NUM包括三个空格字符,存放第一个位置的时候只要进行如下操作:
MOVSI,OFFSETNUM
MOV[SI],BL
其中BL为随机数产生函数产生随机数存放的位置,当取第二个随机数的时候,只需要在操作第一随机数的基础上对SI加1即可,同理,当取第三个随机数的时候,只需要在操作第一随机数的基础上对SI加2即可,这样,三个随机数就以字符串的形式存放在NUM中。
取完三个随机数后,如果玩家没有按下了"S"键则从取第一个随机数开始重新运行。
否则,就开始进行比较,在数据段定义了:
TABLEDB'777666555444333222111567456345234123'
只要从TABLE中不断取出"777","666"……等字符串与NUM比较即可知道NUM中的字符是否为了中奖的字符,比较程序的流程如图3所示:
图3.比较程序的流程图
在程序的一开始将BL置为11,BL是用来移动SI指向TABLE的位置,CX=3表示比较三个字符,然后将TABLE的偏移地址加上44赋给SI,加为44是为了从TABLE最右边的三个字符〔123开始比较,NUM的偏移地址赋给DI,再将[SI]赋给AH,[DI]赋给AL,如果AH等于AL,说明NUM与TABLE中某个中奖子字符串的三个字符中的某同一位置字符一样,那么就比较三个字符中的下一个字符,直到CX=0时,三个字符都比较完,如果三个字符都相等,说明滚筒的三个数字是中奖数字,只要三个字符中有一个不相等,那么就要取TABLE中下一个中奖的子字符串进行比较,获取TABLE中下个中奖字符串的方法就是先将BL自减1,判断BL的值,当BL=0时,说明NUM与TABLE中存放的中奖字符串没有匹配的,也就是玩家没有中奖。
如果BL不等于0,那么在TABLE偏移地址的基础上加上BL*4,因为每个获奖字符串为三个字符,再加上一个空格字符一共四个字符,所以加上BL*4也就指的是下一个中奖字符串的第一个字符的偏移地址。
根据BL的值可以判定NUM与TABLE中哪个中奖的字符串一样,由此决定玩家的奖金。
五.软件设计
1.程序中使用的DOS和BIOS功能
INT10H功能
AH
功能
调用参数
00
设定显示模式
AL=03<80*25分辨率>
02
置光标位置
BH=页号DH=行DL=列
09
设置字符属性
BL=属性CX=字符重复次数
表1.INT10H功能表
INT16H功能
AH
功能
调用参数
返回参数
01
读取缓冲区字符
AL=读取的字符
表2.INT16H功能表
INT21H功能
AH
功能
调用参数
返回参数
08
键盘输入
AL=输入字符
09
显示字符串
DX=串地址
0C
清除输入缓冲区
4C
带返回码结束
AL=返回码
表1.INT21H功能表
2.光标位置设置程序
为了使界面美观,在特定位置输出字符非常重要,为了在程序可以简单的设置光标位置,在程序中设置了一个宏,宏的程序如下:
CURPOSMACROROW,COM;ROW表示行,COM表示列
PUSHAX
PUSHBX
PUSHDX
MOVAH,2;表示调用第10H号中断的2号子程序,用来置光标位置
MOVBH,0;表示第0页
MOVDH,ROW;光标的行
MOVDL,COM;光标的列
INT10H;第10H号中断功能
POPDX
POPBX
POPAX
ENDM
程序中首先将AX,BX,DX压入栈,然后在程序的结尾弹出栈,因为在宏中改变了这三个寄存器的值,这样保证了程序在这个宏运行完之后,不影响AX,BX,DX的值,否则会影响程序的正确运行。
将这三个寄存器压入栈之后,开始设置IN10H的02号子程序的参数,每个参数在程序在有注释。
在以后的程序中如果要设置光标位置,只要调用CURPOSx,y即可改变光标位置,能在一定程度上使程序简洁明了。
整个程序中一共设置了四个宏:
SETCOLOR用来设置字符颜色的,CURPOS用来设置光标位置,PRINT用来打印单个字符,PRINTRESULT用来打印获奖结果,前三个宏的原理相似,PRINTRESULTx,是用来比较x的值来打印不同的获将结果.
3.清除某行字符程序
界面在设置时,不同的行的功能是不一样的,以第11行为例,第11行是用来显示获奖结果,那么如果重新开始游戏后,前一次的获奖结果应当被清除,但不能用清屏的方式来解决问题,我的想法是这样的,在DATA段定义了一空字符串:
CLEARWINDB'','$'
然后在程序中实现如下:
CURPOS11,0;第11行用来显示获将情况
LEADX,CLEARWIN;将第11行清空,CLEARWIN为一长串空格字符串
MOVAH,09H;调用第21H中断9号功能,打印字符串
INT21H
先调用CURPOS这个宏来设置光标的位置,从第11行的第1个字符开始打印这个空字符串,那么这行之前的字符就被空字符覆盖,以达到清除这一行字符的效果。
4.设置滚筒数字
CURPOS9,33;滚筒第一个数字的位置
SETCOLOR1,84H;84H表示红色用高亮
CALLRAND;获取一个随机数
PRINTBL;打倒该随机数
MOVSI,OFFSETNUM;将随机数放在NUM中的第1个位置
MOV[SI],BL
程序首先调用CURPOS来设置数字要显示的位置,在本程序中,三个滚筒的位置<行,列>为:
<9,33>、<9,35>、<9,37>,然后设置该字符的颜色,因为只有一个字符,SETCOLOR中的字符数量参数为1,再调用RAND这个函数产生一随机数,该函数将产生的随机数存放在BL中,那么在调用这个随机函数后,直接调用PRINT这个宏打印BL即可,最后取NUM字符串的偏移地址放在SI中,将BL存放在[SI]中。
在打印第二和第三个滚筒数字的时候与第一个数字基本一样,不同的是实现第二个滚筒数字需要:
INCSI;将随机数放在NUM中的第2个位置
第三个滚筒数字需要:
ADDSI,2;将随机数放在NUM中的第3个位置
这样可以将三个数字存放在NUM这个字符串中,方便以后比较判定是否中奖。
5.中奖与否判定程序
COMPARE:
MOVBL,11;用来比较NUM和TABLE各项的值,BL用来移动TABLE的字符的位置
MOVCX,3;每次只比较三个字符
MOVSI,OFFSETTABLE;将TABLE的偏移地址存入在SI中
ADDSI,44;从TABLE中最右边的三个字符开始比较
MOVDI,OFFSETNUM;将NUM的偏移地址存放在DI中
NUMP:
MOVAH,[SI];将[SI]存放在AH中,SI存放的是地址,[SI]则表示该地址的字符
MOVAL,[DI];将[DI]存放在AL中
CMPAH,AL;比较两个字符
JNZJ1;如果不相等,则取TABLE的另三个字符进行比较
INCSI;取下一个字符地址
INCDI;取下一个字符地址
LOOPNUMP;循环比较,当CX=0时会停止比较,
CMPCX,0
JZJ2
J1:
CMPBL,0
JZLOST
DECBL;BL自减1,表示从TABLE中向左另取三个字符
MOVCX,3;重新将CX置为3,表示比较三个字符,
MOVAL,4;因为TABLE第个字符项为4个字符
MULBL;AL*BL代表要移动的量
MOVAH,0
MOVSI,OFFSETTABLE
ADDSI,AX
MOVDI,OFFSETNUM
JMPNUMP
这段代码是本次设计的核心程序,在程序流程图中有了详细的介绍,这段代码也是根据比较程序的流程图来实现的,程序中的J2是用来打印中奖信息的程序标号,LOST是用来打印未中奖的程序标号。
6.随机数产生函数程序
RANDPROCNEAR
PUSHCX
PUSHDX
PUSHAX
MOVAX,7MOVDX,41H;用端口41H
OUTDX,AX;产生从1到AX之间的随机数了
INAL,DX;产生的随机数AL
MOVBL,AL
ADDBL,30H
POPAX
POPDX
POPCX
RET
RANDENDP
这个方法来自网络,可以方便的产生随机数。
程序像宏一样,还是先将在程序中会改变的寄存器压入栈,然后在结尾弹出栈,保证寄存器在程序运行完之后值不变。
端口41H为8253可编程定时/计时器的第2个计数器通道,第2个计数器使用的是8253的方式二,方式二计数的特点是,计数器从初值开始进行减1操作,直到减到0,然后重新载入初值进行重复操作,当设置了新初值后,并不会影响当前的计数,从下次计数开始才使用新的初值。
有了这样的特点,那么我们可以在41H端口写入初值7,初值7写完之后,计数器不会产即从7开始进行减1操作,只有当前计数完成之后才会有效,这样避免了写初值到读计数器的间隔太短而导致随机数效果不良好,因为用INAL,41H读取计数器中的值时,这个值会因程序的执行时间不同而有变化,而程序执行时间不是一个固定的值,所以计数器的值也是随机的,执行时间越长随机性越强,由此便产生了随机数。
六.调试问题
在编程程序的时候,我也遇到过很多问题,这些问题都是通过查找书籍资料或者网上搜索来解决的,主要遇到的问题如下:
1.输出字符串时发现有乱码
原来字符串没有结束标志’$’,在DATA段定义字符串的时候,在最后面加一个’$’即可。
2.使用JZ跳转的时候出现:
jumpoutofrangebyxxxbytes错误
根据字面意思应该是跳转超出范围,通过查找资料发现JZ是短跳转指令,而JUMP是长跳转指令,那么解决办法可以是先在JZ附近设置一标号JTEMP,JZ可以先跳到JTEMP,然后从JTEMP中利用JUMP指令跳到JZ需要跳到的地方,如此便解决了问题
3.在滚筒旋转的过程中,输入"S",调用第16H中断的1号功能,读取输入缓冲区的字符后,滚筒停止转动,等待玩家开始下一次游戏,但是字符"S"仍然影响这个等待过程中的输入,会提示用户输入错误,因为在等待游戏开始的时候只有"R"和"E"是有效的,其它的都是错误输入。
出现这样的错误,最初怀疑是"S"仍然在缓冲区中,我想查找资料看有没有可以清除输入缓冲区的办法,发现调用第21H中断的0C号功能,可以用来清空输入缓冲区,后来调用该DOS功能即可解决问题。
七.运行效果
1.程序进入时运行效果
程序刚进入时,清空屏幕,显示一些欢迎信息和操作方法,字符均为白色,等待玩家输入。
2.按错键运行效果
在等待玩家输入的时候,如果输入除"R"和"E"之外的键都算是输入错误,提示玩家输入错误,请重新输入。
3.滚筒工作运行效果
三个滚筒的数字不断的变化,同时状态用绿色符"RUNNING"来表示。
4.未能得奖效果
当滚筒的三个数字不属于中奖的数字时,用红色字体告诉玩家未能中奖信息。
5.得奖运行效果
为了测试这个效果,在产生随机数的函数中,将存放随机数的BL直接赋7,以模拟最高奖的情况,一共有12个中奖的情况,三个7是最高的,所以得到12倍的奖金,同时以绿色来显示中奖信息。
6.退出的运行效果
玩家按"E"退出时,友好的告诉玩家已经退出,并欢迎下次光临。
八.总结
此次课程设计花费了我很多的精力和时间,我需要学习很多的新知识,由于课堂时间有限,很多东西老师是不可能讲到的,比如老师不可能在课堂上讲完所用BIOS和DOS功能的调用,为了使做出的效果更好,只有靠自己去查找资料来解决,这些努力给我带来了许多的提升,只有在实践中才能更加理解各种指令的用法,巩固了我的理论知识,同时极大的提高了我的学习兴趣,尤其是在程序可以正确运行的时候,那种成就感让我更加有信心学习汇编语言,同时我发现,一种良好的软件设计思维对任务效果的好坏有着很大的影响,所有不管用什么计算机语言去实现同一功能,但这种思维不会变化,在今后的学习过程中多多培养这种思维。
然而,学无止境,虽然对这次设计总体上感觉上还可以,但是我知道未来的学习将会更加有深度和难度,这次仅仅是开始,未来的挑战只有勇敢的去迎接。
附:
程序清单:
DATASEGMENT
HEADMSG1DB'*******************SLOTMACHINE*******************','$'
HEADMSG2DB'HELLO,WELCOMETOYOU,GOODLUCK!
','$'
HEADMSG3DB'PLEASEPRESS"R"TORUN,"S"TOSTOP,"E"TOEXIT','$'
HEADMSG4DB'*****************************************************','$'
CLEARWINDB'','$'
RESULTDB'RESULT:
','$'
RUNNINGDB'RUNNING','$'
STOPINGDB'STOPING','$'
EXITSTRDB'YOUHAVEEXITTED,WELCOMENEXTTIME!
','$'
LOSTSTRDB'YOUGETNONE,COMEON!
','$'
INPUTERRORDB'INPUTERROR,INPUTAGAINPLEASE!
','$'
TABLEDB'777666555444333222111567456345234123','$'
WIN1DB'01TIMES','$'
WIN2DB'02TIMES','$'
WIN3DB'03TIMES','$'
WIN4DB'04TIMES','$'
WIN5DB'05TIMES','$'
WIN6DB'06TIMES','$'
WIN7DB'07TIMES','$'
WIN8DB'08TIMES','$'
WIN9DB'09TIMES','$'
WIN10DB'10TIMES','$'
WIN11DB'11TIMES','$'
WIN12DB'12TIMES','$'
NUMDB''
WINDB'CONGRATULATION,YOUWIN:
','$'
DATAENDS
STACKSEGMENTSTACK
DB64DUP
>
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
SETCOLORMACRONUM,COLOR;设置字体颜色,NUM:
设置的字数,COLOR:
要设置的颜色
PUSHAX
PUSHBX
PUSHCX
MOVCX,NUM;将字数存放在CX中
MOVBL,COLOR;颜色存放在BL中
MOVAH,09H;调用第10H中断的9号功能,设置在光标位置显示字符及其属性
INT10H
POPCX
POPBX
POPAX
ENDM
CURPOSMACROROW,COM;ROW表示行,COM表示列
PUSHAX
PUSHBX
PUSHDX
MOVAH,2;表示调用第10H号中断的2号子程序,用来置光标位置
MOVBH,0;表示第0页
MOVDH,ROW;光标的行
MOVDL,COM;光标的列
INT10H;第10H号中断功能
POPDX
POPBX
POPAX
ENDM
PRINTMACROC;宏定义定义之后要显示的数字,输出字符
PUSHAX
PUSHDX
MOVDL,C;显示M这个字符,
MOVAH,02H;DL=输出字符
INT21H
POPDX
POPAX
ENDM
PRINTRESULTMACROC;输出获将情况
PUSHAX
PUSHDX
CURPOS11,0;第11行用来显示获将情况
LEADX,CLEARWIN;将第11行清空,CLEARWIN为一长串空格字符串
MOVAH,09H;调用第21H中断9号功能,打印字符串
INT21H
CURPOS11,22
SETCOLOR31,0AH
MOVAH,09H
MOVDX,OFFSETWIN
INT21H
CASE777:
CMPC,0;如果C=0,表示获得最高获
JNZCASE666;如果C不等于0,进行下等级获项的比较
MOVAH,09H;第21号中断的09号功能,输出字符串
MOVDX,OFFSETWIN12;输出所获得的奖项
INT21H
CASE666:
CMPC,1
JNZCASE555
MOVAH,09H
MOVDX,OFFSETWIN11
INT21H
CASE555:
CMPC,2
JNZCASE444
MOVAH,09H
MOVDX,OFFSETWIN10
INT21H
CASE444:
CMPC,3
JNZCASE333
MOVAH,09H
MOVDX,OFFSETWIN9
INT21H
CASE333:
CMPC,4
JNZCASE222
MOVAH,09H
MOVDX,OFFSETWIN8
INT21H
CASE222:
CMPC,5
JNZCASE111
MOVAH,09H
MOVDX,OFFSETWIN7
INT21H
CASE111:
CMPC,6
JNZCASE567
MOVAH,09H
MOVDX,OFFSETWIN6
INT21H
CASE567:
CMPC,7
JNZCASE456
MOVAH,09H
MOVDX,OFFSETWIN5
INT21H
CASE456:
CMPC,8
JNZCASE345
MOVAH,09H
MOVDX,OFFSETWIN4
INT21H
CASE345:
CMPC,9
JNZCASE234
MOVAH,09H
MOVDX,OFFSETWIN3
INT21H
CASE234:
CMPC,10
JNZCASE123
MOVAH,09H
MOVDX,OFFSETWIN2
INT21H
CASE123:
CMPC,11
JZP123;如果C=12,表示结果为123,则输出获奖结果
JNZEXITP;如果C不等于12,什么也不输出,退出宏
P123:
MOVAH,09H
MOVDX,OFFSETWIN1
INT21H
EXITP:
POPDX
POPAX
ENDM
START:
MOVAX,DATA
MOVDS,AX
MOVAH,00h;用来清屏
MOVAL,03H
INT10H
;******************输出程序信息量********************
CURPOS2,0;设置光标位置,此处设为第二行
SETCOLOR66,0FH;设置该行字符颜色,66表示要设置的字符个数,0FH表示为白色
LEADX,HEADMSG1;存放字符串的地址
MOVAH,09H;调用21H中断的第9号功能,显示字符串
INT21H
CURPOS3,0
SETCOLOR52,0FH
LEADX,HE