X86汇编语言程序设计实验报告学院:信息科学与技术学院班级:计科一班学号:13349061姓名:廖远强指导老师:凌应标2015.6.16中山大学操作系统实验报告计科一班1贪吃变色龙游戏设计一、实验目的用汇编语言编程。二、实验内容完成一个汇编语言设计的互动单人游戏程序设计项目。三、实验要求(1)文本方式的显示控制(2)有1个以上的多个移动物体(字符),在屏幕区域内反复移动(3)有数字显示游戏中的内部信息(4)加分项:个性特征丰富,如移动、物体形态或数量变化的不规则性、多种性;键盘交互与控制能力;布局外观吸引眼球能力;适合原型操作系统中运行;同等完成质量提交越早越好。四、开发环境平台工具:dosbox、Notepad++、Nasm、winHex、vmwareworkstaction五、游戏设计步骤我在设计这个贪吃变色龙游戏时,有几个比较重要的步骤:1.龙身的存储;2.龙身的显示;3.龙身的移动;4.龙身移动方向的改变;5.食物的产生和放置;6.吃到食物并生长;7.龙的死亡;8.游戏改进,游戏界面的设计;下面将进行这几个步骤的细致叙述:中山大学操作系统实验报告计科一班2一、龙身的存储一开始是想着,屏幕是二维屏幕,如果可以获得龙身的坐标的话,直接在当前坐标打印蛇身就好了。可是龙身不是只有一个点,而是有许多点,那么该如何存储龙身所有的坐标呢,如果可以像高级语言那个使用数组来存储就好了。那怎么办呢,我想起了这个语句:times510-($-$$)db0,好吧,这个就是用来声明数组的,可以在前面加一个label,这个label就是这个数组的首地址,获得数组的首地址之后就可以访问整个数组了。声明数组的时候要有两个,即龙身的横纵坐标,用这种方法来存储龙身,那么后面的程序写起来就会顺利很多了。其中龙身的头尾坐标要另外存储,后面判断吃食物的,还有撞到自己的会用到。二、龙身的显示龙身用数组来存储之后,想要显示龙身就简单了,只要访问龙身,获得龙身的坐标,然后调用BIOS中断,一个一个打印龙身就可以把我的龙显示出来了。我是调用了10h中断,09h号功能打印‘*’,入口参数坐标dh,dl。中山大学操作系统实验报告计科一班3三、龙身的移动有的龙身的坐标,也可以在屏幕上显示龙身了,那么下一步就是龙身的移动了。因为即使没有键盘输入龙身也应该按照它原来的方向前进的,所以得有一个不用player控制的是龙身前进的步骤。一开始是想着可以调用BIOS中断16h号中断,01h号功能的,即读取键盘状态,可是遇到一个问题,太快了,游戏一开始,迅速撞墙挂掉^_^。想起来之前我们做过的操作系统实验,曾经写过一个时钟中断,想到可以通过时钟中断来刷新龙身,而且这个速度也可以控制。于是很自然的把龙身的移动放到了时钟中断里面了。因为龙身的存储使用数组,打印是获得坐标打印的,而龙身的前进对应的就是坐标的后移,根据前进的特点,就是头部更新,然后尾巴去掉,尾巴的去掉直接打印字符就好了,然后用一个循环把龙身的坐标后移,头坐标更新至新的头坐标就好了,接着就是调用自己写的打印龙身的函数dspSnake就可以了:中山大学操作系统实验报告计科一班4四、龙身移动方向的改变方向可以自己声明一个变量dir,用来存储龙身前进的方向。当没有键盘输入的时候,就沿着这个方向前进。当有输入是,先判断输入是否是方向键(a=leftw=upd=rights=down),如果不是方向键可认为是没有输入,如果输入的方向与原来的方向相同或者相反,也可以认为是没有输入,直接在调到key_in继续等待player输入。如果输入与原来龙身的前进方向垂直,输入有效,改变方向。中山大学操作系统实验报告计科一班5代码有注释,就不再详细说明了。此截图仅仅是输入为left,且与原来的方向垂直,与此类似的代码还有三个,不一一展示。这个在附件的源代码里面有详细的说明注释。五、食物的产生和放置食物的产生应当是随机的,就是要有一个可以产生随机数的程序用来产生食物的横纵坐标。这个在高级语言里面直接用rand就好了,在汇编里面有点麻烦,我上网找了一些方法,最后选择用io端口产生随机数。因为我不确定产生的随机数是不是我想要的范围(因为我在单独测试这个产生随机数程序的时候,在我设置的范围内也会出现光标),所以我对程序做了几点特殊的处理,其中一个就是产生随机数的时候通过用除法获得%的值,用这个值再加或者减一个值以获得我想要的随机数的范围:中山大学操作系统实验报告计科一班6产生纵坐标也是类似的处理。这里有个问题,食物产生之后,如果给龙吃掉了,那么当前位置就要用空白覆盖,或者清屏,清掉原来的食物,然后下一次时钟到来时再产生新的食物,所以时钟进来的时候要有一个判断,判断食物是否存在,类似于一个门栓:六、吃到食物龙吃到食物的定义就是头部坐标和食物的坐标相等,所以只需要做一个横纵坐标的判断即可,不相等继续,如果相等,就是吃到食物,然后龙长大,更新龙身,长度要加一,尾坐标依然要保留:中山大学操作系统实验报告计科一班7七、龙的死亡龙的死亡的定义是撞到墙壁,或者撞到自己。撞到墙壁很好判断,当龙将要前进的时候就判断龙的头部坐标是否有一个已经更墙壁坐标相等了,如果相等,再沿着这个方向前进就会撞墙死掉:龙的第二种死法是撞到自己,这个也不难,只需要比较龙的头部坐标和身体的其它坐标是否相等就可以了,用一个循环就可以实现:首先要比较与原来的尾坐标是否相等:比较头部坐标和龙身的其它坐标是否相等:中山大学操作系统实验报告计科一班8八、游戏改进,游戏界面的设计实现的前面七个功能其实就是可以设计出这个贪吃龙了,游戏已经可以玩了,作业也是可以交了。但是因为是第一次自己写游戏,就想着做好一些,所以才有了这一部分。此部分主要是要给出游戏的基本(指南,设计者等)和界面的个性化和美化:1、Guidance首先打开游戏的时候需要有一个README,这里调用一个BIOS中断,显示字符串:2、右侧游戏信息在游戏进行的时候,我还在屏幕的右侧68-79列位置显示了类似的信息和游戏指南,中山大学操作系统实验报告计科一班9player获得的分数和player从键盘输入的字符:调用了多次这个中断,每个只显示一行内容。因为如果加上0dh,0ah,光标到了下一行的开头,并不是我想要的位置。如果用空格填充又会占用龙身移动的位置。有一个想法是调用BIOS中断设置光标,我自己也用这个中断写了一个函数set_cursor,不过我这里并没有这样做。我在屏幕的右下角位置显示了player从键盘输入的字符;下面截图的前面几行代码是必须的,原因注释已经说的很清楚了:3、右侧墙壁因为上面的信息是在屏幕右侧显示,所以龙身不可以到这个位置,So,龙身移动的范围就要重新设定了,把右边墙壁的纵坐标改为67即可,为了给player相应的信息就应该在68列打印出一堵墙壁:中山大学操作系统实验报告计科一班104、贪吃龙身变色升级成贪吃变色龙自己定义一个变量,color,用来存储此时的颜色,在调用打印龙身函数的时候,打印字符的中断字符属性改为color,即可显示此时的颜色。定义这个变量是为了改变颜色,所以color不能一直不变,因此,我是每用一次这个值我就加一,当等于15的时候,强制置为1(没有0,因为与背景色相同,会看不到):5、吃到金子类似于产生食物那样产生金子‘#’,如果吃到金子,则分数加5分;但是龙不长大。金子的数量要比食物的数量少。金子会闪烁,而且数量比较少。6、GAMEOVER游戏结束的时候告诉player,游戏结束,就是调用一个字符串输出的函数,在屏幕的中心显示GAMEOVER就可以了。中山大学操作系统实验报告计科一班117、待改进没有背景音乐或者说是声音,这里其实可以用一个io端口实现,当龙吃到食物或者金子的时候给出提示音,这个不难,还有不少要改进的地方(比如再次启动游戏),但是不想再去实现了,毕竟真的很忙。。。。六、实验结果实验结果就不废话了,直接看游戏界面截屏吧^_^游戏运行方式,用虚拟机打开MySnake.img软盘,或者将MySnake.com拖进dosbox运行,我的机器直接打开MySnake.com也可以运行,不过视觉效果没有那么好。游戏指南:游戏开始:中山大学操作系统实验报告计科一班12游戏去吃食物龙撞到自己,死亡:中山大学操作系统实验报告计科一班13龙撞到墙壁,死亡:中山大学操作系统实验报告计科一班14七、实验心得实验心得,看着前面已经十多页了,实验心得就简单些吧,只挑关键的讲:1、一开始用引导扇区引导,结果挂了好多次,比如键盘不能输入,时钟不能继续往下进行,字符串也不可以显示;这个bug我调试了好久好久,找了班上的大神帮忙,结果花了一整天依然没有找到什么原因。当时砸电脑的心都有了^_^!!!!!因为我们几个人都认为程序逻辑上没有问题的,这样设计是正确,而且大神还说他的逻辑跟我的是一样的,然而他的可以顺利的进行。他是用dos_box运行.com程序的,我也尝试用这个方法来运行我的程序,好吧,错误没有那么明显。于是乎很自然的想到了我在VMware上运行的时候是要引导扇区的,而在dos_box下运行直接用.com文件就可以了。于是乎也就很自然想到了段寄存器的值的问题了,timer的段地址和主程序的不一样,所以需要在重新设置。把这个bug找到之后,我再花了几个小时就把游戏主体部分写好了,就是已经可以运行了,因为其它功能的实现不难。2、一开始做的时候跟同学讨论了一些,感觉这个游戏的设计很简单,逻辑上不难。只是因为是用汇编,所以有些麻烦,中间出现问题的时候也不容易发现。这里可以总结一些这个游戏的逻辑,其实就是上面的游戏设计步骤啦,不再赘述。。。。。。(看导航的小标题就可以了)3、游戏存在bug:a)当龙吃到食物的时候,尾坐标更新比较慢,应该是我程序逻辑上有点小小的bug,不过这个问题不大。b)另外一个bug是食物的产生有可能会不再屏幕上,这个应该跟io端口有关,因为我是用io端口产生随机数的。而且我还做了特殊的处理,用div指令获得余数确保产生的随机数在我的范围内。可是还是会有问题;c)解决这个问题我采用了键盘输入计数,当player从键盘输入多次之后,屏幕就会刷新,食物重置,以保证龙一定会有食物可以吃。4、实验的目的,内容,和要求没有细致些,因为作为理科生,应该注重本质的东西。5、因为代码比较长,所以我把它放在两个文件里面,其中一个文件类似于函数库,在用的中山大学操作系统实验报告计科一班15时候include进来就可以了。6、其实我起这个名字只是为了好玩啦,其实就是一个贪吃蛇游戏,会变点色,没有什么的。一千多行代码,纯手打,也是不容易啊,累了就开下玩笑呗^_^^_^^_^^_^^_^^_^7、在代码源文件里面,我添加了许多注释,方便老师查看。8、建议在dos_box下运行游戏。9、做这个游戏的时候问了几个同学问题,咨询一下他们一些功能是怎么实现的,当我debug不出的时候也找过他们帮我debug。好耐心,好感动。(他们equ陈榕涛,劳嘉辉,崔家洛(网工))附:代码清单(有详细注释,见附录)计一廖远强2015-06-16附录主程序;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;mySname.asm主程序;此程序所有权归廖远强;国立中山大学信息科学与技术学院13级计科一班;谢谢!!;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^org100h;directionconstantsleftequ97;aupequ119;wrightequ100;ddownequ115;sTdelayequ2;计时器延迟计数key_numberequ12;一个计数器,当长时间找不到食物时;(计数器为零,刷新界面,重置食物gold_numberequ8中山大学操作系统实验报告计科一班16startGame:callclscalldspGameGuide;给出游戏指南callhide_cursor;隐藏光标xorax,axmovah,0in