课程设计任务书
学生姓名: 专业班级:
指导教师: 工作单位:
题目: 打印水仙花数
初始条件:
理论:完成了《汇编语言程序设计》课程,对80X86系列编程结构和指令系统有了较深入的理解,已掌握了汇编语言程序设计的基本方法和技巧。
实践:完成了《汇编语言程序设计》的基本实验,熟悉了汇编语言程序的设计环境并掌握了汇编语言程序的调试方法。
要求完成的主要任务:
进一步理解和掌握较复杂程序的设计方法,掌握子程序结构、宏指令的设计和友好用户界面的设计。具体的设计任务及要求:
1) 键盘输入一个大整数n;
2) 将小于n的水仙花数打印出来(各位数字的立方和等于该数本身);
3) 程序采用子程序结构或宏指令,结构清晰;
4) 友好清晰的用户界面,能识别输入错误并控制错误的修改。
在完成设计任务后,按要求撰写课程设计说明书;对课程设计说明书的具体要求请见课程设计指导书。
阅读资料:
1)《80X86汇编语言程序设计(王元珍等)》例5.12
2)《汇编语言(王爽第3版)》实验1、实验2、实验3
时间安排:
设计安排二周:第18周:完成系统分析及设计,初步代码编写。
第19周:完成程序调试,撰写课程设计报告。
指导教师签名: 2018年 月 日
打印水仙花数
1.需求说明
1.1设计要求:
进一步理解和掌握较复杂程序的设计方法,掌握子程序结构的设计和友好用户界面的设计。
具体的设计任务及要求:
1.输入一个三位整数n;
2.将小于n的水仙花数打印出来(各位数字的立方和等于该数本身);
3.程序采用子程序结构或宏指令,结构清晰;
4.友好清晰的用户界面,能识别输入错误并控制错误的修改。
1.2设计说明
所谓“水仙花数”是指一个3位数,其个、十、百位数字的立方和等于其本身。
1.3功能简述
程序可以输入一个三位数,若输入有误则提示错误,并提示重新输入,若输入正确,系统将显示出所有大于等于100,并且小于等于输入数字的水仙花数。
然后提示是否继续,若用户输入y或Y,则系统回到最开始的状态,若输入n或N,则退出系统,若为其他则提示错误,并重新输入。
2.设计说明(简要的分析与概要设计)
2.1简要分析
2.1.1原理说明
(1)输入阶段:在数据段设置一个输入缓冲区,用于接收输入的字符串,判断输入的数是否为三位数,个位十位百位是否符合要求。若不符合,显示输入错误的信息。
(2)转化阶段:若输入的数符合要求,则将每一个字符转化为十六进制,并求出该数的真正数值,以十六进制形式保存。
(3)判断、输出水仙花数阶段:从(cx)=100开始循环,求(cx)的个位十位百位,并求其立方和,看看是否和(cx)自身相等。若相等,则(cx)为水仙花数,将其输出。若不相等,则(cx)+1,继续循环判断。当(cx)=输入数时循环结束,此时打印出了大于等于100,小于等于输入数的所有水仙花数。功能完成。
(4)询问阶段:询问用户是否重新执行该过程。是则重复以上阶段,否则退出程序。
2.1.2程序流程图
(画出程序实现基本流程图,可以在学校网站下载Visio2016用其中的流程图功能绘制)
2.2 数据段设计
data segment
messsage1 db 0dh,0ah,'Please input a number(100<=number<=999):','$';输入一个三位数
messsage2 db 0dh,0ah,'Do you want to continue(y/n)?','$';是否继续
messsage3 db 0dh,0ah,'shuixianhuashu:',0ah,'$';打印水仙花数
error db 0dh,0ah,'Input error,please input again!','$';输入异常
charNum db 10;存放输入的数(字符串),最多可以输入9个数
db 0
db 10 dup(0);最后一个人字符留给回车
realNum dw ?;存放由字符转换来的数
cxNum db 3 dup(?);存放100~输入数字间的每个数
data ends
3.主要子程序(或宏指令)设计与描述
(程序中一些常用模块如键盘输入、显示输出、数制转换(十进制转二进制、十六进制)、程序退出等用子程序或宏指令实现,使主程序代码看着简洁)
(1)子程序:input。
功能:输入一个三位数。
说明:在数据段定义了输入缓冲区charNum,输入三位数的百、十、个位字符分别存放于charNum[2]、 charNum[3] 、charNum[4]中。(charNum[0]存放缓冲区的最大容量,charNum[1]存放实际输入的字符数)
(2)子程序:convert。
功能:将输入的字符转化为十六进制数,并处理错误输入。
说明:通过比较输入字符的ASCII码来判断个位、十位是否为0-9,百位是否为1-9,若不是,处理错误,重新调用子程序input。由于输入的三位数是字符形式,所以要将其每位数由ASCII码转化为16进制数(sub al,30h)。最后由个、十、百位求出真实的三位数值,存入realNum中。
(3)子程序:judge。
功能:判断并显示水仙花数。
说明:将cx置为100,将其作为计数器 ,循环赋值为100到输入数间的每一个三位数。(cx)/10的余数是个位(存入cxNum[2]),再将商/10得到的余数是十位(存入cxNum[1]),商是百位(存入cxNum[0])。用bx存放三位数的立方和,并与(cx)比较,若相等,则将cxNum中的数转换为字符后打印。此后(cx)+1,当(cx)=输入数时循环结束。
4.源程序与执行结果
4.1源程序代码
data segment
inputMess db 0dh,0ah,'Please input a number(100<=number<=999):','$';输入一个三位数
repeatMess db 0dh,0ah,'Do you want to continue(y/n)?','$';是否继续
printMess db 0dh,0ah,'shuixianhuashu:',0ah,'$';打印水仙花数
errorMess db 0dh,0ah,'Input error,please input again!','$';输入异常
charNum db 10;存放输入的数(字符串),最多可以输入9个数
db 0
db 10 dup(0);最后一个人字符留给回车
realNum dw ?;存放由字符转换来的数
cxNum db 3 dup(?);存放100~输入数字间的每个数
data ends
code segment
assume ds:data,cs:code
;************************************************************************************
;主程序:main
;功能:控制程序主流程
main proc far
start:
mov ax,data
mov ds,ax
go:;输入三位数,判断并显示水仙花数
call input
call judge
again:;询问是否继续
lea dx,repeatMess
mov ah,9
int 21h
mov ah,1
int 21h
cmp al,89;Y的ASCII码
je go
cmp al,121;y的ASCII码
je go
cmp al,78;N的ASCII码
je exit
cmp al,110;n的ASCII码
je exit
lea dx,errorMess
mov ah,9
int 21h
jmp again
exit:
mov ah,4ch
int 21h
main endp
;************************************************************************************
;子程序:input
;功能:输入一个三位数
input proc near
lea dx,inputMess
mov ah,9
int 21h
mov ah,0ah
lea dx,charNum;从键盘输入字符串
int 21h
call convert
ret
input endp
;************************************************************************************
;子程序:convert
;功能:将输入的字符转化为十六进制数,并处理错误输入
;寄存器分配:
;al:存放每一位数
;bx:存放转换完毕的三位数
convert proc near
xor bx,bx
xor dx,dx
xor ax,ax
cmp charNum+1,3;判断输入的是否为三位数
jne err
mov al,charNum[4];判断个位是否为0~9
cmp al,47;0的ASCII码是48
jbe err
cmp al,58;9的ASCII码是57
jge err
sub al,30h;将字符转化为数
mov bx,ax
mov al,charNum[3];判断十位是否为0~9
cmp al,47
jbe err
cmp al,58
jge err
sub al,30h
mov dh,10
mul dh;10*(al)->ax
add bx,ax;
mov al,charNum[2];判断百位是否为1~9
cmp al,48
jbe err
cmp al,58
jge err
sub al,30h
mov dh,100;100*(al)->ax
mul dh
add bx,ax
mov realNum,bx;将转化后的数存入realNum
jmp return
err:;处理错误输入
lea dx,errorMess
mov ah,9
int 21h
call input
return:
ret
convert endp
;************************************************************************************
;子程序:judge
;功能:判断并显示水仙花数
;寄存器分配:
;ax:存放每一位数的平方
;bx:存放三位数立方之和
;cx:计数器,存放从100到输入三位数间的所有三位数
judge proc near
lea dx,printMess
mov ah,9
int 21h
mov cx,100
digit_cube:
;将百位的立方存入bx
mov ax,cx
mov dh,100
div dh;(al)=百位数
mov cxNum[0],al;百位存入cxNum[0]
mov dh,al;以下三行求百位数的立方,结果在ax中
mul dh
mul dh
mov bx,ax
;将十位的立方加入bx
mov ax,cx
mov dh,10
div dh;(ah)=余数(个位),(al)=商(百位十位)
mov ah,0
div dh;商/10,(ah)=余数(十位),(al)=商(百位)
mov cxNum[1],ah;十位存入cxNum[1]
mov al,ah
mov dh,ah
mul dh
mul dh
add bx,ax
;将个位的立方加入bx
mov ax,cx
mov dh,10
div dh;(ah)=余数(个位)
mov cxNum[2],ah;个位存入cxNum[2]
mov al,ah
mov dh,ah
mul dh
mul dh
add bx,ax
mov dx,cx
cmp dx,bx;将当前数(cx)与位数平方之和(bx)比较
je print;相等则是水仙花数,打印
mov ax,realNum
cmp cx,ax;将当前数(cx)与输入的数(ax)比较
je stop;相等则终止
inc cx;否则将当前数(cx)+1继续下轮比较
jmp digit_cube
print:
;打印百位
mov dl,cxNum[0]
add dl,30h
mov ah,2
int 21h
;打印十位
mov dl,cxNum[1]
add dl,30h
mov ah,2
int 21h
;打印个位
mov dl,cxNum[2]
add dl,30h
mov ah,2
int 21h
mov dl,20h
int 21h
mov ax,realNum
cmp ax,cx
je stop
inc cx
jmp digit_cube
stop:
ret
judge endp
;************************************************************************************
code ends
end start
4.2 测试
4.2.1 测试用例
输入数字:
① 错误输入:99
② 错误输入:066
③ 错误输入:2333
④ 正确输入:345
⑤ 正确输入:999
是否继续:
① 错误输入:1
② 错误输入:t
③ 正确输入:y
④ 正确输入:n
4.2.2 测试结果
5.总结
在这次汇编课程设计中,我更加深入地理解了相关的汇编知识,对于相关汇编指令的运用更加熟悉。我在这个过程中体会到了用汇编语言编程的不易,数据在寄存器、内存单元中的存储、转移真的是一件需要非常小心处理的事,每一步的结果都需要仔细计算求证,否则极易出错。
此外,我还深刻体会到绘制流程图对于程序设计的重要性,只有在写代码之前清楚、完备地考虑程序流程,才能做到事半功倍。依照程序流程图,一点一点地分析、实现程序模块,代码的编写就变得容易起来,相关错误的查找也会变得更加轻松。
6.参考资料
《80X86汇编语言程序设计》王元珍等 著
《汇编语言(第三版)》 王爽 著