这里水仙花数指严格意义上的水仙花数,即若一个数满足这个数等于它的百位数、十位数、个位数的立方和,那么这个数是水仙花数。
一、设计要求
具体的设计任务及要求:
- 输入一个三位整数n;
- 将小于n的水仙花数打印出来(各位数字的立方和等于该数本身);
- 程序采用子程序结构或宏指令,结构清晰;
- 友好清晰的用户界面,能识别输入错误并控制错误的修改。
二、功能简述
程序可以输入一个三位数,若输入有误则提示错误,并提示重新输入,若输入正确,系统将显示出所有大于等于100,并且小于等于输入数字的水仙花数。
然后提示是否继续,若用户输入y或Y,则系统回到最开始的状态,若输入n或N,则退出系统,若为其他则提示错误,并重新输入。
三、模块说明
子程序名 | 功能 | 基本实现 |
---|---|---|
GET_INPUT | 获取键盘输入三位数字 | 通过INT 21H号中断获取键盘输入 |
INPUT_CHECK | 输入检测,判断是否为数字 | 通过两次比较,第一次与‘0’比较,判断是否不小于,第二次与‘9’比较,判断是否不大于,都满足则ok |
JUDGE_lOW_BORDER | 判断输入数字是否是大于100的 | CMP与0进行比较判断即可 |
INPUT_ERROR | 输入错误处理模块 | 输出错误信息,同时自增CX,让循环仍然能够获取三位数字,在继续循环 |
INPUT_RIGHT | 输入正确处理模块 | 存储输入数字,循环继续 |
CONTINUE | 循环继续 | 通过LOOP S2来使循环得到三位数字,同时输出三位数字以检测模块是否正确执行 |
SWITCH_INPUT | 输入转换,即将输入字符转换为一个二进制数字 | 将输入数字减去’0’即可获取输入数字(字符),的二进制(原因:ASCII码),再讲位数乘上10或者100 |
SWITCH_NUM_SYS | 进制转换及存储 | 将当前循环中的数字转化为三个数存储,如123转化为1, 2, 3分别存储,用于后面计算水仙花数 |
CAL_CUBE | 计算水仙花立方 | 将存储的三个数字分别计算立方并相加 |
JUDGE_NARC_NUM | 判断水仙花数,是则显示 | 通过CMP指令比较数字或者立方和是否相等,相等则显示 |
IF_CONTINUE | 一轮之后是否继续 | 通过获取键盘输入判断 |
CONTINUE_CHECK | 是否继续输入判断 | 通过CMP指令,让输入字符与 y,Y,n,N比较并跳转到相应模块 |
CONTINUE_NEXT_ROUND | 继续下一轮 | 跳转到START |
CONTINUE_ERROR | 继续下一轮判断的时候输入错误 | 显示输入错误信息,并JMP到IF_CONTINUE继续输入模块 |
STOP | 输入n退出 | 通过MOV AX, 4C00H 和INT 21H结束程序 |
四、测试用例
-
测试结果说明:
(1) 输入789 ,输出水仙花数407, 371, 370, 153
(2) 输入y,程序继续,重新输入上限数值
(3) 输入367,输出水仙花数 153
(4) 输入y,程序继续,重新输入上限数值
(5) 输入067,程序发现其输入数字小于100,提示输入数字太小,重新输入
(6) 输入a,提示输入错误重新输入数值
(7) 输入 371,输出水仙花数 371,370,153
(8) 输入N,退出程序
测试结果:
代码如下:
COMMENT /**
Copyright <2018> <Zhao Nan>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
USERNAME: Zhao Nan
COMPLETE TIME: 2018-1-4
DESCRIBE: Print the number of daffodils between 100 and n(the number you input)
*/
.386
ASSUME CS:CODES, DS:DATA, SS:STACK
DATA SEGMENT USE16
MSG1 DB 0AH, 0DH, 'The shuixianhuashu is : $' ;0AH, 0DH 代表换行和回车
MSG2 DB 0AH, 0DH, 'Please input a three-digit number: ', '$'
MSG3 DB 0AH, 0DH, 'Input Error, Please the number again:', '$'
MSG4 DB 0AH, 0DH, 'The three-digit number is: ', '$'
MSG5 DB 0AH, 0DH, 'Do you want to continue(y or Y/n or N): ', '$'
MSG6 DB 0AH, 0DH, 'Input Error, Please input again:', '$'
MSG7 DB 0AH, 0DH, 'The number you input is too little.$'
NUMS DB 3 DUP(0), 0AH, 0DH, '$' ; 存储三位数字,后续中可以存储当前的三位数字,如:循环到了456,则分别存储4,5,6
CUBES DW 3 DUP(0) ; 存储立方数字,分别是 百位,十位,个位数字的立方
DATA ENDS
STACK SEGMENT USE16 STACK
DB 100 DUP(0)
STACK ENDS
CODES SEGMENT USE16 ;使用 16位
;------------------------main-----------------------------
START:
CALL GET_INPUT ;获取键盘输入
CALL JUDGE_lOW_BORDER ;判断输入数字是否是大于100的
CALL SWITCH_INPUT ;输入转换存在 CX 中,CX控制循环
SUB CX, 100 ;不能输出100以下,所以这里减100,注意后面使用的时候加100或者用其他操作
LOOP1:
CALL SWITCH_NUM_SYS ;将二进制转化为三个数字到 NUMS[0] NUMS[1] NUMS[2] 中
CALL CAL_CUBE ;求水仙花立方
JMP JUDGE_NARC_NUM ;判断水仙花数,是则显示
NEXT:
LOOP LOOP1 ;循环到 0为止
JMP NEAR PTR IF_CONTINUE
MOV AX, 4C00H ;程序终止
INT 21H
;---------------------------------------------------------
;---------------------------------------------------------
;判断是否为水仙花数
JUDGE_NARC_NUM:
MOV AX, CUBES[0]
ADD AX, CUBES[2]
ADD AX, CUBES[4]
SUB AX, 100 ;由于不能输出100,注意
CMP AX, CX
JNE NEXT
JE DISPLAY ;相等则显示
;显示水仙花数
DISPLAY:
LEA DX, MSG1 ;显示水仙花数
MOV AH, 09H
INT 21H
MOV AH, 2
MOV DL, NUMS[0] ;百位数字
ADD DL, 30H ;转换为数字显示, ASCII加上 48 即为字符
INT 21H
MOV DL, NUMS[1] ;十位数字
ADD DL, 30H
INT 21H
MOV DL, NUMS[2] ;个位数字
ADD DL, 30H
INT 21H
JMP NEXT
;键盘输入
GET_INPUT:
MOV CX, 3 ;三次输入数字
MOV AX, DATA
MOV DS, AX
MOV BX, 0 ;输入次数
LEA DX, MSG2 ;显示提示输入
MOV AH, 09H
INT 21H
LOOP2:
MOV AH, 01H ;从键盘输入一个字符, 其ASCII存放在 AL 中
INT 21H
JMP INPUT_CHECK ;输入检测判断
;输入检测
INPUT_CHECK:
CMP AL, '0'
JB INPUT_ERROR ;输入ASCII码小于 0 输入错误
CMP AL, '9'
JA INPUT_ERROR ;输入ASCII码大于 9 输入错误
JNA INPUT_RIGHT ;否则输入正确
;输入错误
INPUT_ERROR:
LEA DX, MSG3 ;输出错误的信息模板
MOV AH, 09H
INT 21H
;INC CX
MOV CX, 4
MOV BX, 0
JMP CONTINUE
;输入正确
INPUT_RIGHT:
MOV NUMS[BX], AL ;存储输入
INC BX
JMP CONTINUE ;继续循环
;继续
CONTINUE:
LOOP LOOP2
LEA DX, MSG4 ;输出正确的数字
MOV AH, 09H
INT 21H
LEA DX, NUMS
MOV AH, 09H
INT 21H
RET ;返回主程序,RET从堆栈中取出 IP
;-----------------------------------------------------
; 判断输入数字是否是大于100的
JUDGE_lOW_BORDER:
CMP NUMS[0], '0'
JE NUM_IS_LIttle
RET
;输入数字太小
NUM_IS_LIttle:
LEA DX, MSG7
MOV AH, 09H
INT 21H
JMP START
;输入转换存在 CX 中,CX控制循环
SWITCH_INPUT:
MOV CX, 0
MOV CL, NUMS[2]
SUB CL, '0'
MOV AL, 10
MOV BL, NUMS[1]
SUB BL, '0'
MUL BL
ADD CX, AX
MOV AL, 100
MOV BL, NUMS[0]
SUB BL, '0'
MUL BL
ADD CX, AX
RET
;----------------------------------------------------------
;进制转换存在 NUMS[0], NUMS[1], NUMS[2] 中
SWITCH_NUM_SYS:
MOV AX, CX
ADD AX, 100
MOV BL, 100
DIV BL ;AL=百位数, AH=余数
MOV NUMS[0], AL ;百位数字
MOV AL, AH
MOV AH, 0
MOV BL, 10
DIV BL
MOV NUMS[1], AL ;十位数字
MOV NUMS[2], AH ;个位数字
RET
;求水仙花立方
CAL_CUBE:
MOV AL, NUMS[0] ;三次连乘即可
MOV AH, 0
MOV BX, AX
MUL BX
MUL BX
MOV CUBES[0], AX
MOV AL, NUMS[1]
MOV AH, 0
MOV BX, AX
MUL BX
MUL BX
MOV CUBES[2], AX
MOV AL, NUMS[2]
MOV AH, 0
MOV BX, AX
MUL BX
MUL BX
MOV CUBES[4], AX
RET
;-----------------------------------------------------------------
;-----------------------------------------------------------------
;输出水仙花数之后的判断是否继续
IF_CONTINUE:
LEA DX, MSG5 ;显示提示输入
MOV AH, 09H
INT 21H
MOV AH, 01H ;从键盘输入一个字符, 其ASCII存放在 AL 中
INT 21H
JMP CONTINUE_CHECK
;是否继续输入判断
CONTINUE_CHECK: ;判断是否输入的是 y, Y, n, N
CMP AL, 'y'
JE CONTINUE_NEXT_ROUND
CMP AL, 'Y'
JE CONTINUE_NEXT_ROUND
CMP AL, 'n'
JE STOP
CMP AL, 'N'
JE STOP
JNE CONTINUE_ERROR
;继续
CONTINUE_NEXT_ROUND:
JMP NEAR PTR START
;退出
STOP:
MOV AX, 4C00H ;程序终止
INT 21H
;继续输入错误
CONTINUE_ERROR:
LEA DX, MSG6 ;输出错误的信息模板
MOV AH, 09H
INT 21H
JMP IF_CONTINUE
;----------------------------------------------------
CODES ENDS
END START
参考教材:王爽的《汇编语言》