(一)实验名称
递归程序设计求N阶乘
(二)实验内容和要求
设计一个汇编程序完成y=n!的计算。
要求:(1)能够根据用户输入的n值计算其阶乘,结果以十进制数显示;
(2)基于递归程序结构,模块划分合理,具有清晰的入口和出口。
(三)实验目的
(1)感受和学习递归程序的设计方法、技巧,完成递归程序设计
(2)学会运用堆栈传递参数的方法和技巧
(3)进一步感受和学习汇编语言程序设计的方法、技巧和调试过程(四)实验日期、时间和地点
时间:2010年11月22日
地点:微机高级实验室
(五)实验环境(说明实验用的软硬件环境及调试软件)
使用masm for windows
(六)实验步骤(只写主要操作步骤,要简明扼要,还应该画出程序流程图或实验电路的具体连接图)
(七)实验结果(经调试通过的源程序的所有代码,应包含必要的说明文字)DATAS SEGMENT
OPE DW 0,0,0,0
RESULT DB 16 DUP(0),'H',0DH,0AH,0AH,'$'
NUM DB 3,0,3 DUP(0)
MESS1 DB'Please input N(key Enter to quit):',0DH,0AH,'$' ERR_MESS DB'Error number,try again!',0DH,0AH,0AH,'$'
FUNC DB 0,0,'!','=','$'
DATAS ENDS
STACKS SEGMENT STACK
DW 1000 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
DS_STR MACRO BUF ;显示字符串的宏
PUSH DX
PUSH AX
LEA DX,BUF
MOV AH,09H
INT 21H
POP AX
POP DX
ENDM ;——————————————————————————————————
————
SR_STR MACRO BUF;输入字符串的宏
PUSH DX
PUSH AX
LEA DX,BUF
MOV AH,0AH
INT 21H
POP AX
POP DX
ENDM ;——————————————————————————————————————
START:
MOV AX,DATAS
MOV DS,AX
MOV ES,AX
LOP1:
MOV CX,16;对RESULT清零
LEA DI,RESULT
MOV AL,0
REP STOSB
MOV CX,4;对OPE清零
LEA DI,OPE
MOV AX,0
REP STOSW
DS_STR MESS1;显示提示信息
SR_STR NUM;输入N
MOV DL,0AH;输出换行
MOV AH,2H
INT 21H
CMP [NUM+1],0;直接回车则退出
JZ OVER
CMP [NUM+1],1
JNZ LABEL_2
CMP [NUM+2],'1';输入一位数,是1~9,则继续,否则输出错误信息,并跳转到开始
JB ERR_NUM
CMP [NUM+2],'9'
JA ERR_NUM
MOV BL,[NUM+2];把输入的ASCII码转换成数字存入BX中
SUB BL,30H
MOV BH,0
JMP GO_ON
LABEL_2:
CMP [NUM+2],'1';输入二位数,是10~99,则继续,否则输出错误信息, JB ERR_NUM
CMP [NUM+2],'9'
JA ERR_NUM
CMP [NUM+3],'0'
JB ERR_NUM
CMP [NUM+3],'9'
JA ERR_NUM
MOV AL,[NUM+2];把输入的ASCII码转换成数字存入BX中
SUB AL,30H
MOV BL,10
MUL BL
MOV BL,[NUM+3]
SUB BL,30H
MOV BH,0
ADD BX,AX
GO_ON:
MOV [OPE],BX;循环初始化
MOV CX,BX
DEC CX
JCXZ CX_ZERO
DO1:
DEC BX
CALL MUL_big
LOOP DO1
JMP GO_ON1
CX_ZERO:
MOV [OPE],1
GO_ON1:
MOV AX,[OPE];将结果转换成ASCII码
LEA DI,RESULT
ADD DI,15
CALL BIN_TO_NUM
MOV AX,[OPE+2]
CALL BIN_TO_NUM
MOV AX,[OPE+4]
CALL BIN_TO_NUM
MOV AX,[OPE+6]
CALL BIN_TO_NUM
CMP [NUM+1],1;输出'n!='
JE NUM_EQU_1
MOV AL,[NUM+2]
MOV [FUNC],AL
MOV AL,[NUM+3]
MOV [FUNC+1],AL
LEA DX,FUNC
JMP OUTPUT_STR
NUM_EQU_1:
MOV AL,[NUM+2]
MOV [FUNC+1],AL
LEA DX,FUNC
INC DX
OUTPUT_STR:
MOV AH,9H
INT 21H
LEA SI,RESULT;从第一个非零的地方输出结果,然后回到开始
DEC SI
LOOP1:
INC SI
CMP BYTE PTR [SI],30H
LOOPZ LOOP1
MOV AH,9H
MOV DX,SI
INT 21H
JMP LOP1
ERR_NUM:
DS_STR ERR_MESS;输出错误信息,然后回到开始
JMP LOP1
OVER:
MOV AH,4CH
INT 21H
MUL_big PROC NEAR;相乘,完成OP1和BX的乘,结果保存在OPE起始的四个字里PUSH AX
PUSH SI
PUSH DI
PUSH CX
PUSH DX
MOV CX,BX
DEC CX
JCXZ NEXT
MOV AX,[OPE]
MOV SI,[OPE+2]
MOV DI,[OPE+4]
MOV DX,[OPE+6]
DO:
ADD [OPE],AX
ADC [OPE+2],SI
ADC [OPE+4],DI
ADC [OPE+6],DX
LOOP DO
NEXT:
POP DX
POP CX
POP DI
POP SI
POP AX
RET
MUL_big ENDP
BIN_TO_NUM PROC NEAR;将AX中的十六进制数转换成相应ASCII码,结果保存在[DI]~[DI+3]中
PUSH CX
PUSH BX
MOV CX,4
AGAIN:
PUSH CX
MOV CX,4
AGAIN1:
RCR AX,1
RCR BL,1
LOOP AGAIN1
SHR BL,1
SHR BL,1
SHR BL,1
SHR BL,1
CMP BL,9
JBE LABEL_BE
ADD BL,7
LABEL_BE:
ADD BL,30H
MOV [DI],BL
DEC DI
POP CX
LOOP AGAIN
POP BX
POP CX
RET
BIN_TO_NUM ENDP
CODES ENDS
END START。