一、设计题目编写计算N!的程序(数值N由键盘输入,结果在屏幕上输出。N的范围为0-65535,即刚好能被一个16位寄存器容纳)。二、开发目的由于当N值较大时(N10),N的阶乘计算很繁琐并且计算容易出错。所以可以编写计算N!的程序,利用计算机强大的计算能力计算N!。这不仅能节省繁琐计算的时间,而且得到的N!的积比起手工算的要准确。三、设计方案N的阶乘为1*2*3……(N-1)*N,N的范围为(0000H—FFFFH),N!以字为单位存在一个或几个定义的数据段中。若已算到(n-1)!,假如它占4个字的空间,接下来它乘以n的原理,如图1所示。1图1(n-1)!*n的原理因此计算N!的算法可以这样编写,当前n!的值为被乘数,内容存在str2中,单位为字,n+1的值为乘数,存在str1中,单位也为字。被乘数从str2首地址中内容开始与乘数相乘,得到32位的积,它的低16位覆盖掉当前被乘数所在存储空间的内容。接着str2下一个字的内容与乘数相乘,也得到32位的积,前一个积的高16位与现在积的低16位相加,它们的和覆盖掉当前被乘数所在存储空间的内容,若它们的和有进位,把进位加到现在积的高16位。直到把str2中内容乘完。然后乘数增1,循环上面的内容。直到执行完(N-1)!*N输入的N为4位16进制数,输出也为16进制数。四、程序流程图开始输入N值2YNYNYN判断N值长度N是否大于5把N值从ASCH码转化为4位16进制数N=0?n←1m←1判断N!的积接下来的内容是否要存到附加段n←n+1m←m*n输出超出取值范围输出N!为1n←n+1m←m*n3NNYY五、程序清单data1segmentinput1db'pleaseinputthenumber:','$'input2db10,?,10dup(?);输入的16进制数errordb'Outofrange','$'output1db'Theansweris1','$'output2db'Theansweris:','$'str1dw100dup(?);保存1—N(后一个数覆盖前一个数)str2dw7000hdup(?);N!乘积的值(1)pdw100dup(?);上一个乘积的高16位data1endsdata2segmentstr3dw7fffhdup(?);N!乘积的值(2)data2endscodesegmentassumecs:code,ds:data1,es:data2org100h;程序从偏移地址100h开始执行start:movax,data1;程序初始化movds,axmovax,data2moves,ax;初始化结束movah,9leadx,input1int21hnN?输出m,也就是N!结束nN?4movah,2;回车movdl,0dhint21hmovah,2;换行movdl,0ahint21hmovah,0ah;输入所需求的N值(N为16进制数)leadx,input2int21hmovah,2movdl,0dhint21hmovah,2movdl,0ahint21hleabx,input2moval,[bx+1];判断输入的N值是否超过FFFFHcmpal,4jas1movcl,4;把输入的N值有ASCH码转成16进制数movah,[bx+2]moval,[bx+3]cmpal,39hjaabc1def1:shlal,clcmpah,39hjaabc2def2:shrax,clmovdh,almovah,[bx+4]moval,[bx+5]cmpal,39hjaabc3movcl,4def3:shlal,clcmpah,39hjaabc4def4:shrax,clmovdl,al;转换结束movax,dx;判断N值是否为0cmpax,0jzs25jmps3abc1:subal,37hjmpdef1abc2:subah,37hjmpdef2abc3:subal,37hjmpdef3abc4:subah,37hjmpdef4s1:movah,9;若N值超过FFFFH的输出leadx,errorint21hjmpnexts2:movah,9;N值为1的输出leadx,output1int21hjmpnexts3:movcx,ax;计算N的阶乘movax,1mov[str1],ax;N从1开始,作为乘数leasi,str2mov[si],ax;N!的积从1开始,作为被乘数movax,0mov[p],ax;(n-1)!的乘积的低16位与n相乘后积的高16位movbx,1;开始N!的乘积占一个字空间movWORDptr[p+10],0;(n-1)!的乘积的高16位与n相乘后积的低16位和(n-1)!的乘积的低16位与n相乘后积的高16位的和的进位,初始进位为0movah,9leadx,output2int21hmovah,2movdl,0dhint21hmovah,2movdl,0ahint21hlop2:mov[p+2],bx6lop3:movax,[si];(n-1)!的乘积从最低16位的内容与n相乘movdx,[str1]muldxclcaddax,[p+10];前一次的进位与当前乘积的低16位内容相加jnck1;判断是否产生进位movWORDptr[p+10],1addax,[p];前一个积的高16位与现在积的低16位相加jmpk2k1:addax,[p]jnck3;判断是否产生进位movWORDptr[p+10],1jmpk2k3:movWORDptr[p+10],0k2:mov[si],axmov[p],dxaddsi,2decbxcmpbx,0jnzlop3movbx,[p+2]clcadddx,[p+10]cmpdx,0jzre;判断(n-1)!乘积的最高16位内容与n的乘积的高16位是否为0incbxmov[si],dxre:movax,[str1]cmpax,9000h;判断是N!乘积的内容高位部分是否要存到es中jncre1jmpre2re1:cmpcx,1jas4re2:incWORDptr[str1];乘数增1leasi,str2movWORDptr[p],0movWORDptr[p+10],0looplop2decbxmovcx,bx7lop4:addsi,2looplop4incbxaddbx,bxincsijmplop5s4:incWORDptr[str1];若N的值超过8000h,8000h*8001h*8002h*Nmov[p+6],bxmov[p+8],bxleasi,str2leadi,str3moves:[di],dxmovWORDptr[p],0movWORDptr[p+10],0movbx,1deccxlop6:mov[p+4],bxlop7:movax,[si]movdx,[str1]muldxclcaddax,[p+10]jnck4movWORDptr[p+10],1addax,[p]jmpk5k4:addax,[p];前一个积的高16位与现在积的低16位相加,产生进位jnck6movWORDptr[p+10],1jmpk5k6:movWORDptr[p+10],0k5:mov[si],axaddsi,2mov[p],dxdecWORDptr[p+6]movax,[p+6]cmpax,0jnzlop7movax,[p+8]8mov[p+6],axlop8:movax,es:[di]movdx,[str1]muldxclcaddax,[p+10]jnck7movWORDptr[p+10],1addax,[p]jmpk8k7:addax,[p];前一个积的高16位与现在积的低16位相加,产生进位jnck9movWORDptr[p+10],1jmpk8k9:movWORDptr[p+10],0k8:moves:[di],axadddi,2mov[p],dxdecbxcmpbx,0jnzlop8movbx,[p+4]clcadddx,[p+10]cmpdx,0jzre4incbxmoves:[di],dxre4:incWORDptr[str1]leasi,str2leadi,str3movWORDptr[p],0movWORDptr[p+10],0deccxcmpcx,0jnzlop6decbxmovcx,bxlop9:adddi,2looplop9incbx9addbx,bxincdilop10:decbx;若N8000h,输出N!乘积的高位内容moval,BYTEptres:[di]movch,almovcl,4shral,clcmpal,09hjaop3addal,30hjmpip3op3:addal,37hip3:movah,2movdl,alint21hmoval,chandal,0fhcmpal,09hjaop4addal,30hjmpip4op4:addal,37hip4:movah,2movdl,alint21hdecdicmpbx,0jnzlop10movbx,[p+6]decbxmovcx,bxlop11:addsi,2looplop11incbxaddbx,bxincsilop5:decbx;输出N!的乘积moval,BYTEptr[si]movch,almovcl,410shral,clcmpal,09hjaop1addal,30hjmpip1op1:addal,37hip1:movah,2movdl,alint21hmoval,chandal,0fhcmpal,09hjaop2addal,30hjmpip2op2:addal,37hip2:movah,2movdl,alint21hdecsicmpbx,0jnzlop5next:movah,1int21hmovah,4chint21hcodeendsendstart六、程序运行结果与分析若输入的16进制数N为000A(10进制为10),程序运行后输出的N!应为375F00(H)。程序运行结果如图2所示。11图2N=000A若输入的16进制数N为0064(10进制为100),虽然答案不能手算出来,但根据理论N!的低位应该为0。程序运行结果如图3所示。图3N=0064根据这两个结果,我认为该程序应该是正确的。七、实验总结本次实验是编写N!的程序。在这次实验中我遇到了许多困难,一些是自己考虑不周引起的,一些是自己知识掌握不牢靠引起的,还有一些是由于自己粗心引起的。所有的这些坎坷,都催化着我那稚嫩的程序慢慢地完善和严谨。一开始我没考虑到阶乘乘积的前一个字中的内容与乘数相乘后的积的高16位与阶乘乘积的后一个字的内容与乘数相乘所得的积的高16位相加后,它们的和产生进位的问题。在做到数据段已存不下阶乘的积,要把多出的数据放到附加段时。由于知识掌握的不牢靠,不知道附加段的数据传输要在[di]前加es。导致程序输出一直出错。在快完成程序时,由于自己的马虎。定义好附加段的内容后,忘加了dup(?)。导致算N很大时的阶乘一直出错。虽然这次实验编写的难度很大,但我感到我的汇编能力比起以前有了很大的提高,同时也巩固我所学的知识。最后,程序虽然能实现0到FFFFH的阶乘了,但我感到这程序还不友好。因为你输入的数据必须是4位16进制数,如果高位没有,必须加0,补足4位。这就多了一步,即要把所要求的10进制数先12转成16进制数才能运行程序。所以我认为程序可以把输入部分优化,使输入10进制数,在程序中转成对应的16进制数。