计算机硬件课程设计——计算N!的程序
- 格式:doc
- 大小:269.50 KB
- 文档页数:10
目录一、设计题目 (2)二、开发目的 (2)三、设计方案以及论证 (2)四、程序流程图 (2)五、程序清单 (5)六、程序运行结果分析与预测 (9)七、总结 (9)参考文献 (9)一、设计题目编写计算N!的程序(数值N由键盘输入,结果在屏幕上输出。
N的范围为0-65535,即刚好能被一个16位寄存器容纳)。
二、开发目的随着科技的发展数学中的问题解决方案有多种多样,计算机的发展给人们在数学中无法用手工计算的问题得以解决,这次我们开发一道程序实现一个最大数可达到十六位的二进制数的阶乘。
三、设计方案以及论证对于N!,如果单纯的N计算阶乘,N值在一个很小的范围内计算起来是很简单,在计算机中也很好实现,但是当N值达到一定的数值就要考虑计算结果对于一个16为二进制的寄存器或存储器是否能够容纳。
若果不能容纳该怎么实现。
怎么样才能将这么一个大的数据存储起来就是此次实验重点讨论的问题,一般的在汇编语言中只能实现两个数相乘,当计算N!时是指N个数相乘,这样我们就要先两个数相乘,再将乘积存储在缓存中再与下一个数相乘,乘积再继续存储在缓存中,随着乘数的增多缓存的位数也不断增大,这样利用缓存就将一个很大的数存储起来。
四、程序流程图图一程序的主流程图①.根据题目要求将主流程图规划出如图一所示,首先是先定义各个基本段(数据段、堆栈段、代码段),之后是输入N值,这里调用INPUT_N子程序将要计算的N值输入并将输入的N值赋给BP,判断BP是否为1或0即是判断输入的N值是否为1或0,如果输入值为0或1,由于0或1的阶乘为1所以直接调用JGXS子程序显示结果1.若判断N值不为1或0将缓冲区初始化为N,而BP的值自减1这时判断BP是否为1,若为1则显示缓冲区的计算结果,若不为1将缓冲区的值与BP相乘,乘积存储在缓冲区中,然后循环,BP值自减1并重新判断BP的值是否为1,反复循环直到BP的值为1,最终将计算结果存储在缓冲区中,最后将缓冲区中的数据显示出来,N!计算结束。
②.对于输入N值的子程序INPUT_N,其将输入的N值存储在寄存器DX(DX开始清零)中,由键盘输入一个字符首先判断是否为回车键,如果是回车结束;如果不是继续判断,先将AL值减30H判断AL是否小于0,是重新输入;不是判断AL是否小于0FH,是将DX 乘16加AL;不是的话先将AL值减07H,判断AL是否小于等于0FH,如果是将DX乘16加AL;不是判断AL是否小于2AH或大于2FH如果是重新输入;不是的话将AL值减20H,将DX乘16加AL,判断结束继续输入字符知道输入回车键跳出。
③.对于子程序XS_YW、XS_DB、XS_DW、JGXS都是围绕缓冲区中结果的显示,首先XS_YW功能是显示一位16进制,XS_DB功能是显示一个字节数,XS_DW功能是显示一个字两个字节数,JGXS功能是利用循环将整个缓冲区中的数显示出来。
这些子程序是通过嵌套使用最终达到显示计算结果。
图二输入N值流程图图三显示单个16进制数图四显示一个字节数图五显示一个字图六显示计算结果五、程序清单DA TA SEGMENT ;数据段定义开始INPUT DB 'please input the N!',0DH,0AH,'$'OUTPUT DB 'the result is: $'ERROR DB 'input error! input once more!',0DH ,0AH,'$'LEN DW 1CF DW ?BUF DW 6550H DUP(0) ;定义缓冲存储区的大小DA TA ENDS ;数据段定义结束STACK SEGMENT STACK 'STACK' ;堆栈段定义开始DW 32 DUP(?)STACK ENDS ;堆栈段定义结束CODE SEGMENT ;代码段定义开始ASSUME CS: CODE, DS:DA TA, ES:DATA, SS:STACKSTART:MOV AX, DA TAMOV DS,AXMOV ES, AXMOV AH, 09H ;9号字符串显示功能LEA DX,INPUTINT 21H ;显示输入提醒字符CALL INPUT_N ;调用输入子程序提取N值MOV BP, DX ;将N值赋给BPCMP BP, 0JZ JGWECMP BP, 1JZ JGWE ;比较N值是否为0或1LEA SI,BUFMOV [SI],DX ;缓冲区初始化值为NSKT: DEC BPCMP BP,0001H ;将BP自减1之后判断是否为1,是1的话退出乘积循环JZ JGXS ;BP为1的时候跳到子程序显示结果XOR BX,BX ;BX清零MOV WORD PTR CF,0 ;标志位清零MOV CX,LEN ;将目前缓冲区的长度赋给CXLSC: MOV AX, [SI+BX]MUL BPADD AX,CFJNC DWCCINC DXDWCC: MOV [SI+BX],AXMOV CF,DXINC BXINC BXLOOP LSC ;实现BP与缓冲区低位到高位的数相乘乘积任然存放在缓冲区CMP DX, 0000HJZ TSFINC WORD PTR LENMOV [SI+BX],DXTSF: JMP SKT ;跳到乘积开始阶段使BP自减1并判断BP是否为1,JGWE: LEA SI,BUFMOV WORD PTR [SI],1 ;当N为0或1时结果为1CALL JGXS ;调用子程序显示为1的结果JGXS PROC NEARMOV AH, 02HMOV DL, 0DHINT 21HMOV AH, 02HMOV DL, 0AHINT 21HMOV AH, 09HLEA DX,OUTPUTINT 21HMOV CX,LENMOV BX,CXDEC BXSHL BX,1XHXS: MOV AX, [SI+BX]CALL XS_DWDEC BXDEC BXLOOP XHXSMOV AX,4C00HINT 21HJGXS ENDP ;逐个显示缓冲区中的结果直到显示完结束XS_DB PROC NEARMOV BL, ALMOV DL, BLMOV CL, 04ROL DL, CLAND DL, 0FHCALL XS_YW :显示高位MOV DL, BLAND DL, 0FHCALL XS_YW ;显示低位RETXS_DB ENDP ;显示一个字节数XS_YW PROC NEARADD DL, 30HCMP DL, 3AHJB XS_ZFADD DL, 27HXS_ZF:MOV AH, 02HINT 21HRETXS_YW ENDP ;显示一个16进制数一位XS_DW PROC NEARPUSH BXPUSH CXPUSH DXPUSH AXMOV AL, AHCALL XS_DB ;显示高位POP AXCALL XS_DB ;显示低位POP DXPOP CXPOP BXXS_DW ENDP ;显示一个字的数INPUT_N PROC NEARPUSH CXReget: XOR DX, DXGo_on: MOV AH, 01HINT 21HCMP AL, 0DH ;输入字符判断是否为回车,是结束输入执行N!计算JZ EnterCMP AL, 20H ;判断输入值是否为合法的十六进制中的数JZ Wrong ;不是显示输入错误,提醒重新输入SUB AL, 30HJB Wrong ;不是合法十六进制字符,提醒重新输入CMP AL, 0AHJB Right ;是合法字符继续输入CMP AL,11HJB WrongSUB AL, 07HCMP AL, 0FHJBE RightCMP AL, 2AHJB WrongCMP AL, 2FHJA WrongSUB AL, 20HRight: MOV CL, 04HSHL DX,CLXOR AH, AHADD DX ,AXJMP Go_on ;当输入为合法字符时继续输入Wrong: MOV AH, 02HMOV DL, 0DHINT 21HMOV AH, 02HMOV DL, 0AHINT 21HMOV AH, 09HLEA DX,ERRORINT 21HJMP Reget ;当为不合法字符时提醒重新输入Enter: POP CXRETINPUT_N ENDPCODE ENDSEND START六、程序运行结果分析与预测①.程序运行结果当输入程序经过汇编生成asm文件后,链接生成obj文件后,执行jjf跳出提醒输入字符的字符串please input the N!,当输入N值为23、5和a0时显示结果如图七所示。
图七程序运行结果②.图示结果可以看出程序可以达到预期的结果,当输入的N值为不同大小时可以根据计算结果的不同控制输出的长度,输入的值是以16进制计算,输出的值也是以16进制的形式表示出来。
七、总结在此次实验遇到不少问题,开始阶段拿到题目认为很简单就是一般的阶乘利用一个寄存器值自减1就可以达到要求,但是细想之下发现当N值达到一定数值时计算结果远非一个寄存器所能容纳的,这里就遇到一个问题就是怎么处理阶乘不断增大而又超出了一个寄存器所能存储的范围的数,在网上搜集了资料和咨询老师、同学,经过思考了解到利用缓冲存储可以处理当N值到达一定数值后计算阶乘产生的较大是计算结果。
简单的讲就是先将缓冲区初始化为N,BP赋值为N-1,用缓冲区的值与BP相乘乘积存储在缓冲区中,再将BP值自减1,再用缓冲区的值与自减1后的BP相乘,乘积依然存储在缓冲区中,如此循环直到BP值为1结束,这样就解决了计算结果存储的问题。
在程序中考虑到输入为十进制,输出为十进制会给程序带来很大麻烦;所以选用输入为十六进制,输出也为十六进制。
这样就产生一个问题就是怎么样知道键盘输入的字符就是合法的十六进制中的数值,在这里通过调用子程序INPUT_N输入数值N,在这个子程序中当键盘每输入一个字符就与ASCII中值比较;首先判断是否为回车,是就结束N值的输入计算N!;不是就判断是否合法,合法就加入到存储N值的DX寄存器中,不合法就重新输入。
到这里计算N!的程序的基本框架就设计好了。
我相信此次实验也是对一个人耐力的考验,要针对每一个问题取思考怎么去解决它,怎么解决才是最好、最简便的方法。
参考文献[1] 程启明,黄云峰,计算机硬件技术[M] 北京:中国电力出版社2012.。