汇编语言程序设计——打印水仙花数

实验目的

       在对80x86系列编程结构和指令系统有了较深入的理解、已掌握了汇编语言程序设计的基本方法和技巧、熟悉了汇编语言程序的设计环境并掌握了汇编语言程序的调试方法的基础上,进一步理解和掌握较复杂程序的设计方法,掌握子程序结构、宏指令的设计和友好用户界面的设计。

实验任务

       采用DOSBox模拟Intel 8086(16位)处理器,使用汇编语言编写16位程序,完成以下实验程序设计任务及要求:

  • 使用键盘输入一个整数n(100≤n≤999);
  • 将小于等于n的水仙花数打印出来;

水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI)、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrong number)。水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身。

  • 程序采用子程序结构宏指令,结构清晰;
  • 友好清晰的用户界面,能识别输入错误并控制错误的修改。

程序设计说明与描述

功能简述

       启动程序,用户可以输入一个三位数,若输入有误则提示错误,并提示重新输入;若输入正确,系统将显示出所有大于等于100,并且小于等于该输入数字的水仙花数。
       此后,程序提示是否继续。若用户输入’y’或’Y’,则系统回到最开始的状态;若输入’n’或’N’,则退出系统;若输入其他则提示错误,并提示重新输入。

程序流程图

程序流程图

数据段设计

       设计了BUFFER_TRANSFORM、OUTPUT1~ OUTPUT7、BUFFER数据段、RESULT共计11个数据段。这些数据段存储的数据的含义如下:

  • BUFF_TRANSFORM:存储数字的每一位的ASCII码(存储数字转换成的字符串)。在判断是否是水仙花数时,用于临时存储该数字的每一位数字的ASCII码;在输出水仙花数时,用于临时存储该数字的每一位数字的ASCII码。
  • OUTPUT1:存储输入数字的提示。
  • OUTPUT2:存储输入错误的提示。
  • OUTPUT3:存储是否继续的提示。
  • OUTPUT4:存储输出水仙花数(Narcissistic Number)的提示。
  • OUTPUT5:存储未找到水仙花数的提示。
  • OUTPUT6:存储程序结束的提示。
  • OUTPUT7:存储空格。
  • OUTPUT8:存储回车换行符。
  • BUFFER:设置输入字符串长度为4,存储输入的字符串长度,存储输入信息。
  • RESULT:存储计算结果。
DATA	SEGMENT
	;存储数字的每一位的ASCII码(存储数字转换成的字符串)
	BUFFER_TRANSFORM	DB 0,0,0,'$'
	OUTPUT1	DB	"Please input a number (100<=number<=999):",'$'		;存储输入数字的提示
	OUTPUT2	DB	"Input error , please input again ! ",0AH,0DH,'$'	;存储输入错误的提示
	OUTPUT3	DB	"Do you want to continue (y/n) ? ",'$'				;存储是否继续的提示
	OUTPUT4 DB	"Narcissistic Number: ",'$'							;存储输出水仙花数(Narcissistic Number)的提示
	OUTPUT5 DB	"Not Found!",'$'									;存储未找到水仙花数的提示
	OUTPUT6	DB	"Press any key to continue ! ",0AH,0DH,'$'			;存储程序结束的提示
	OUTPUT7	DB	' ','$'				;存储空格
	OUTPUT8	DB	0AH,0DH,'$'			;存储回车换行符
	BUFFER	DB	4,0,4 DUP (0)		;设置输入字符串长度为4,存储输入的字符串长度,存储输入信息
	RESULT	DW	4 DUP (0)			;存储计算结果
DATA	ENDS

子程序设计与描述

  • 子程序名称:CHANGE_LINE
    子程序功能:输出回车换行。
    子程序参数:无。
  • 子程序名称:OUTPUT_ERROR_INFO
    子程序功能:输出错误提示。
    子程序参数:无。
  • 子程序名称:DTOC
    子程序功能:将数字转化为十进制字符串。
    子程序参数:获取AX每一位的值,转换成ASSCII码,存入BUFFER_TRANSFORM。
  • 子程序名称:CHECK_Narcissistic_Number
    子程序功能:判断数字是否为水仙花数。
    子程序参数:判断AX是否为水仙花数。若该数是水仙花数,CX=0;若该数不是水仙花数,CX≠0。
  • 子程序名称:WRITE
    子程序功能:将水仙花数写入RESULT区。
    子程序参数:将水仙花数AX写入RESULT区,DI加二。

源程序代码

ASSUME	CS:CODE,DS:DATA,SS:STACK
DATA	SEGMENT
	;存储数字的每一位的ASCII码(存储数字转换成的字符串)
	BUFFER_TRANSFORM	DB 0,0,0,'$'
	OUTPUT1	DB	"Please input a number (100<=number<=999):",'$'		;存储输入数字的提示
	OUTPUT2	DB	"Input error , please input again ! ",0AH,0DH,'$'	;存储输入错误的提示
	OUTPUT3	DB	"Do you want to continue (y/n) ? ",'$'				;存储是否继续的提示
	OUTPUT4 DB	"Narcissistic Number: ",'$'							;存储输出水仙花数(Narcissistic Number)的提示
	OUTPUT5 DB	"Not Found!",'$'									;存储未找到水仙花数的提示
	OUTPUT6	DB	"Press any key to continue ! ",0AH,0DH,'$'			;存储程序结束的提示
	OUTPUT7	DB	' ','$'				;存储空格
	OUTPUT8	DB	0AH,0DH,'$'			;存储回车换行符
	BUFFER	DB	4,0,4 DUP (0)		;设置输入字符串长度为4,存储输入的字符串长度,存储输入信息
	RESULT	DW	4 DUP (0)			;存储计算结果
DATA	ENDS

STACK	SEGMENT
	DW	8	DUP	(0)
STACK	ENDS

CODE	SEGMENT

START:
	MOV	AX,DATA						;初始化
	MOV	DS,AX
	
	MOV	AX,STACK					;建栈
	MOV	SS,AX
	MOV	SP,16
	
	MOV DI,0
	MOV CX,4
CLEAR_RESULT:						;清除由上一个输入计算出来的水仙花数
	MOV	WORD PTR [RESULT+DI],0
	ADD DI,2
	LOOP CLEAR_RESULT
	
INPUT:								;输入数字
	MOV	AH,09H						;显示提示
	MOV	DX,OFFSET OUTPUT1
	INT	21H
	
	MOV	AH,0AH						;获取输入的字符串
	MOV	DX,OFFSET BUFFER
	INT	21H
	CALL CHANGE_LINE
	
	MOV	AL,[BUFFER+1]				;检查字符串长度
	MOV	AH,0
	CMP	AX,3
	JE	CHECK_NUM					;若长度为3,检查每一个字符是否在范围内
	
INPUT_ERROR_1:						;输入错误
	CALL OUTPUT_ERROR_INFO			;输出输入错误提示
	JMP	INPUT						;返回,重新输入
	
CHECK_NUM:							;检查输入的每一位字符的ASCII码是否符合要求(是否是符合要求的数字)
	CMP	BYTE PTR [BUFFER+2],'0'		;检查第一位字符
	JBE	INPUT_ERROR_1				;小于等于'0',输入错误
	CMP	BYTE PTR [BUFFER+2],'9'
	JA	INPUT_ERROR_1				;大于'9',输入错误
	
	CMP	BYTE PTR [BUFFER+3],'0'		;检查第二位字符
	JB	INPUT_ERROR_1				;小于'0',输入错误
	CMP	BYTE PTR [BUFFER+3],'9'
	JA	INPUT_ERROR_1				;大于'9',输入错误
	
	CMP	BYTE PTR [BUFFER+4],'0'		;检查第三位字符
	JB	INPUT_ERROR_1				;小于'0',输入错误
	CMP	BYTE PTR [BUFFER+4],'9'
	JA	INPUT_ERROR_1				;大于'9',输入错误
	
	;将输入的数计算出来,放入DX
	MOV	AL,[BUFFER+2]
	SUB	AL,30H						;计算出百位上的数字
	MOV	BL,100
	MUL	BL							;乘以100
	
	MOV	DX,AX						;百位乘以100的结果存储到DX
	
	MOV	AL,[BUFFER+3]
	SUB	AL,30H						;计算出百位上的数字
	MOV	BL,10
	MUL	BL							;乘以10
	
	ADD DX,AX						;DX加上十位乘以10的结果
	
	MOV	AL,[BUFFER+4]				;计算出百位上的数字
	SUB	AL,30H
	MOV	AH,0
	
	ADD	DX,AX						;DX加上个位,得到输入的数
	MOV	AX,DX						;将输入的数据存储到AX
	
	MOV	DI,0
LOOP_CHECK_Narcissistic_Number:
	CALL CHECK_Narcissistic_Number	;检查AX是否为水仙花数
	CMP CX,0
	JNE	NEXT						;若CX≠0,则该数不是水仙花数,检查AX-1是否为水仙花数
	CALL WRITE						;若CX=0,则该数是水仙花数,记下该水仙花数
NEXT:
	DEC	AX							;AX自减
	
	CMP	AX,100						;若AX>=100,继续循环
	JAE	LOOP_CHECK_Narcissistic_Number
	
	MOV	AH,09H						;输出水仙花数提示
	MOV	DX,OFFSET OUTPUT4
	INT	21H
	
	CMP WORD PTR [RESULT],0
	JNE FOUND						;若第一个结果不等于0,则找到了水仙花数
	
	MOV	AH,09H						;输出未找到水仙花数的提示
	MOV	DX,OFFSET OUTPUT5
	INT	21H

	
FOUND:
	MOV	CX,4
	MOV	DI,0						;DI:输出寻址控制
SHOW_NUM:							;将记下水仙花数输出
	MOV	AX,[RESULT+DI]
	ADD	DI,2
	CMP	AX,0
	JE	END_SHOW_NUM				;若该数为0,结束输出
	CALL DTOC						;将水仙花数的每一位变成ASCII码放入BUFFER_TRANSFORM
	
	MOV	AH,09H						;输出该水仙花数(ASCII码)
	MOV	DX,OFFSET BUFFER_TRANSFORM
	INT	21H
	
	MOV	AH,09H						;输出空格
	MOV	DX,OFFSET OUTPUT7
	INT	21H
	
	LOOP SHOW_NUM					;循环输出
	
END_SHOW_NUM:
	CALL CHANGE_LINE
	
AGAIN:
	MOV	AH,09H						;输出是否继续提示
	MOV	DX,OFFSET OUTPUT3
	INT	21H
	
	MOV	AH,1						;获取输入的字符
	INT	21H
	CALL CHANGE_LINE
	
	CMP	AL,'n'
	JE	END_PROGRAM					;输入'n',程序结束
	CMP	AL,'N'
	JE	END_PROGRAM					;输入'N',程序结束
	CMP	AL,'y'
	JE	BACK						;输入'y',程序继续
	CMP	AL,'Y'						;输入'y',程序继续
	JNE	INPUT_ERROR_2
	
BACK:								;返回程序开始部分,程序继续
	JMP	FAR	PTR	START				;跳转回(JMP FAR)程序开始部分

INPUT_ERROR_2:						;输入错误
	CALL OUTPUT_ERROR_INFO			;输出输入错误提示
	JMP	AGAIN						;返回,重新输入
	
END_PROGRAM:
	MOV	AH,09H						;输出程序结束提示
	MOV	DX,OFFSET OUTPUT6
	INT	21H
	
	MOV	AX,4C00H
	INT	21H

;名称:CHANGE_LINE
;功能:输出回车换行
;参数:无
CHANGE_LINE:
	MOV	AH,09H
	MOV	DX,OFFSET OUTPUT8
	INT	21H
	RET

;名称:OUTPUT_ERROR_INFO
;功能:输出错误提示
;参数:无
OUTPUT_ERROR_INFO:
	MOV	AH,09H
	MOV	DX,OFFSET OUTPUT2
	INT	21H
	RET

;名称:DTOC
;功能:将数字转化为十进制字符串
;参数:获取AX每一位的值,转换成ASSCII码,存入BUFFER_TRANSFORM
DTOC:
	MOV	SI,2
	MOV	CX,3
	MOV	BL,10
GET_NUM:							;获取该数每一位的值,转换成ASSCII码,存入BUFFER_TRANSFORM
	DIV	BL	
	ADD	AH,30H
	MOV	[BUFFER_TRANSFORM+SI],AH
	MOV	AH,0
	DEC	SI
	LOOP GET_NUM
	
	RET

;名称:CHECK_Narcissistic_Number
;功能:判断数字是否为水仙花数
;参数:判断AX是否为水仙花数
;返回:若该数是水仙花数,返回CX≠0;若该数不是水仙花数,返回CX=0
CHECK_Narcissistic_Number:
	PUSH AX							;保护数据
	CALL DTOC						;计算AX每一位的数字
	
	MOV	CX,3
	MOV	DX,0
	MOV	SI,0
ADD_NUM:							;计算每一位的立方和
	MOV	AL,[BUFFER_TRANSFORM+SI]
	SUB AL,30H
	MOV	AH,0
	MOV	BL,AL
	MUL	BL
	MUL	BL
	ADD DX,AX
	INC	SI
	LOOP ADD_NUM
	
	POP	AX							;恢复数据
	MOV	CX,AX
	SUB CX,DX						;原数与计算结果相减,若该数是水仙花数,CX=0;若该数不是水仙花数,CX≠0
	RET

;名称:WRITE
;功能:将水仙花数写入RESULT区
;参数:将水仙花数AX写入RESULT区,DI加二
WRITE:
	MOV	[RESULT+DI],AX
	ADD	DI,2
	RET

CODE	ENDS
	END	START

文章推荐

博客:汇编语言程序设计(第三版,王爽著)实验

参考文献

[1]王爽.汇编语言程序设计(第三版), 北京:清华大学出版社,2013.
[2]钱晓捷.汇编语言程序设计(第五版),北京:电子工业出版社,2018
[3]王元珍,曹忠升,韩宗芬.80x86汇编语言程序设计,湖北:华中科技大学出版社,2005

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值