课程设计报告.docx
《课程设计报告.docx》由会员分享,可在线阅读,更多相关《课程设计报告.docx(32页珍藏版)》请在冰点文库上搜索。
课程设计报告
课程设计报告
课程微机原理课程设计
题目杨辉三角实现
系别物理与电子工程学院
年级09专业电子信息工程
班级学号
学生姓名
指导教师职称
设计时间2012-3-19~2012-3-31
目录
引言2
第一章杨辉三角简介2
1.1杨辉三角历史2
1.2杨辉三角性质2
第二章汇编语言简介4
2.1汇编语言概况4
2.2汇编语言优点及缺点4
2.3杨辉三角实现要求5
第三章程序设计流程图6
第四章子程序设计7
4.1输入子程序7
4.2杨辉三角算法子程序8
4.3计算输出数字长度子程序9
4.4计行前数字间空格子程序9
4.5输出子程序11
4.6课程设计小结13参考文献13
附录14
附录A14
附录B18
杨辉三角实现
引言
中国古代数学家在数学的许多重要领域中处于遥遥领先的地位。
中国古代数学史曾经有自己光辉灿烂的篇章,而杨辉三角的发现就是十分精彩的一页。
杨辉三角形,又称贾宪三角形,帕斯卡三角形,是二项式系数在三角形中的一种几何排列。
第一章杨辉三角简介
1.1杨辉三角历史
北宋人贾宪约1050年首先使用“贾宪三角”进行高次开方运算。
11世纪中国宋代数学家杨辉在《详解九章算法》里讨论这种形式的数表,并说明此表引自11世纪前半贾宪的《释锁算术》,并绘画了“古法七乘方图”。
故此,杨辉三角又被称为“贾宪三角”。
元朝数学家朱世杰在《四元玉鉴》(1303年)扩充了“贾宪三角”成“古法七乘方图”。
意大利人称之为“塔塔利亚三角形”(TriangolodiTartaglia)以纪念在16世纪发现一元三次方程解的塔塔利亚。
在欧洲直到1623年以后,法国数学家帕斯卡在13岁时发现了“帕斯卡三角”。
布莱士·帕斯卡的著作Traitédutrianglearithmétique(1655年)介绍了这个三角形。
帕斯卡搜集了几个关于它的结果,并以此解决一些概率论上的问题,影响面广泛,PierreRaymonddeMontmort(1708年)和亚伯拉罕·棣·美弗(1730年)都用帕斯卡来称呼这个三角形。
1.2杨辉三角性质
1、每行数字左右对称,由1开始逐渐变大,然后变小,回到1。
2、第n行的数字个数为n个。
3、第n行数字和为2^(n-1)。
(2的(n-1)次方)
4、每个数字等于上一行的左右两个数字之和。
可用此性质写出整个帕斯卡三角形。
5、将第2n+1行第1个数,跟第2n+2行第3个数、第2n+3行第5个数……连成一线,这些数的和是第2n个斐波那契数。
将第2n行第2个数,跟第2n+1行第4个数、第2n+2行第6个数……这些数之和是第2n-1个斐波那契数。
6、第n行的第1个数为1,第二个数为1×(n-1),第三个数为1×(n-1)×(n-2)/2,第四个数为1×(n-1)×(n-2)/2×(n-3)/3…依此类推。
7.两个未知数和的n次方运算后的各项系数依次为杨辉三角的第(n+1)行。
图1-2-1杨辉三角图1-2-2杨辉三角数学公式
第二章汇编语言简介
2.1汇编语言概况
根据本次设计要求:
通过汇编语言编写汇编程序要求能够在提示信息下,从计算机键盘任意输入一个数据,在输出提示信息后显示相应的杨辉三角。
下面对汇编语言作简单的介绍。
汇编语言(AssemblyLanguage)是面向机器的程序设计语言。
在汇编语合中,用助记符(Memoni)代替操作码,用地址符号(Symbol)或标号(Label)代替地址码。
这样用符号代替机器语言的二进制码,就把机器语言变成了汇编语言。
于是汇编语言亦称为符号语言。
使用汇编语言编写的程序,机器不能直接识别,要由一种程序将汇编语言翻译成机器语言,这种起翻译作用的程序叫汇编程序,汇编程序是系统软件中语言处理系统软件。
汇编程序把汇编语言翻译成机器语言的过程称为汇编。
汇编语言是一种功能很强的程序设计语言,也是利用计算机所有硬件特性并能直接控制硬件的语言。
汇编语言,作为一门语言,对应于高级语言的编译器,需要一个“汇编器”来把汇编语言原文件汇编成机器可执行的代码。
高级的汇编器如MASM,TASM等等为我们写汇编程序提供了很多类似于高级语言的特征,比如结构化、抽象等。
在这样的环境中编写的汇编程序,有很大一部分是面向汇编器的伪指令,已经类同于高级语言。
现在的汇编环境已经如此高级,即使全部用汇编语言来编写windows的应用程序也是可行的,但这不是汇编语言的长处。
汇编语言的长处在于编写高效且需要对机器硬件精确控制的程序。
2.2汇编语言优点及缺点
汇编语言直接同计算机的底层软件甚至硬件进行交互,它具有如下一些优点:
(1)能够直接访问与硬件相关的存储器或I/O端口;
(2)能够不受编译器的限制,对生成的二进制代码进行完全的控制;
(3)能够对关键代码进行更准确的控制,避免因线程共同访问或者硬件设备共享引起的死锁;
(4)能够根据特定的应用对代码做最佳的优化,提高运行速度;
(5)能够最大限度地发挥硬件的功能。
同时还应该认识到,汇编语言是一种层次非常低的语言,它仅仅高于直接手工编写二进制的机器指令码,因此不可避免地存在一些缺点:
(1)编写的代码非常难懂,不好维护;
(2)很容易产生bug,难于调试;
(3)只能针对特定的体系结构和处理器进行优化;
(4)开发效率很低,时间长且单调。
2.3杨辉三角实现要求
内容:
在提示信息下,从计算机键盘任意输入一个数据,在输出提示信息后显示相应的杨辉三角。
具体要求:
(1)要有提示信息的输出显示,例如程序执行时直接显示输出提示信息“Pleaseinputanumber:
”然后等待用户从计算机键盘输入具体数值,例如输入“4”,然后换行显示下一步提示信息,例如“TheYanghuitriangle:
”最后显示通过程序获得的杨辉三角如下:
1
121
1331
14641
1331
121
1
(2)分析杨辉三角具体算法,计算结果要求正确。
输出的杨辉三角要求上下左右对称显示,上下分别为两个等腰三角形的形式。
即要求分析总结每行行首空格数量,及三角中各个数之间空格的安排方法;
(3)要求最少要能够输出10阶的杨辉三角;
提高要求:
增大阶数(最少到20阶),可任意选择正反三角显示。
程序设计流程图
首先程序开始时在电脑上显示输入提示信息,提醒输入的操作数只能是1到10之间的正整数,超过这个范围或太小则显示提示信息输入的数过大。
得到杨辉三角的阶数之后即调用一个算法子程序来求相应阶数的每一个数值,每求出一个数值即将其数压入堆栈中保存起来,方便以后输出数字时直接调用。
算完之后,通过外层循环di计数输出每一行,与此同时又通过内层循环si计数输出一行中的每一个数,在输出数字时通过调用show子程序将数字均以十进制输出,在输出数值的时候通过showspace函数来控制数与数之间的空格及行前空格的输出,上半部分的数字输出之后将其所有数值及空格格式都存在一个预制的存储单元内,然后直接实现逆序输出,这样最终能在屏幕中打印出一个菱形的杨辉三角。
主程序流程图如图3.1示:
图3.1主程序流程图
第三章子程序设计
4.1输入子程序
输入用int16ah为0这一功能,从键盘读字符,字符存在al中,输入时用cmp判断令其只能输入字符’0’~‘9’每次输入的字符转化为十进制存并阔展为字存入ax中,再将ax与初始为0的bp交换,再将ax乘以十后与bp相加,结果存在bp中,再返回输入,这样就能输入两位数。
SHURPROC
PUSHCX
PUSHBX
XORBP,BP
MOVBX,10
MOVCX,3
INPUT:
MOVAH,0;键盘输入数据存在AL中
INT16H
CMPAL,0DH;以回车结束输入
JZOK
CMPAL,'0';只允许输入0~9
JBINPUT
CMPAL,'9'
JAINPUT
MOVAH,0EH;显示有效输入
INT10H
SUBAL,30H;化ASCII为十进制
CBW;字节扩展为字
XCHGAX,BP
MULBX;扩大10倍
ADDBP,AX;加一位
LOOPINPUT
OK:
CMPCX,03H
JZEXIT
NOP;数值结果在BP中
POPBX;恢复用到的寄存器
POPCX
RET
SHURENDP
4.2杨辉三角算法子程序
求某m行n列的数C(n,m)时采用递归的方法求出该数具体算法是:
{C(n,m)=1(n{C(n,m)=C(n-1,m-1)+C(n-1,m)(n>m)
即某位置组合数等于上一行左右两数之和,先算出左肩上的数并压栈保存,再次调用C过程求出右肩上的数并压栈保存,左肩与右肩的数相加从而可以求出下一行的组合数吗,其间存在递归调用,直至求出最大的那个数才返回初始调用的call的下一个语句。
CPROC
PUSHBP
MOVBP,SP
SUBSP,2;预留一个存储位置
MOVBX,[BP+6];保存M到BX
CMPBX,[BP+4];如果M=N返回1
JZL1
CMPBX,0;如果M=0返回1
JZL1
MOVAX,[BP+4];保存N到AX
DECAX;AX=AX-1
DECBX;BX=BX-1
PUSHBX
PUSHAX
CALLC;返回上一行左边的那个数
MOV[BP-2],AX;保存左肩膀上的数
MOVAX,[BP+4];以下5句同理,返回上一行右肩膀上的数
DECAX
PUSH[BP+6]
PUSHAX
CALLC
ADDAX,[BP-2];和左肩膀上的数相加得出该组合数
JMPL2
L1:
MOVAX,1
L2:
MOVSP,BP
POPBP
RET4;AX返回组合数
CENDP
4.3计算输出数字长度子程序
将此数不断除以十,每除一次计数加1,当al即商为0时停止返回计数值即长度。
例如:
计算输出数字最大长度以便分配行间行前空格时,n阶的最大数应该是最后一行中间那个数即C(n,n/2),将此数不断除以十,每除一次计数加1,当al即商为0时停止返回计数值即最大长度。
GETDIGITPROC
PUSHDX
MOVBX,10
XORDX,DX
NEXT:
CMPAX,0
JLEOK2
DIVBL
ANDAX,0FFH
INCDX
JMPNEXT
OK2:
MOVAX,DX
POPDX
RET
GETDIGITENDP
4.4计行前数字间空格子程序
先定义一个可以接受输入ax个空格的子程序输出行前空格时,n阶杨辉三角的i行行前空格数=(n-i)*cl,cl是最大长度,某数与下一个数字间空格数=数的最大长度cl+cl-该数的长度。
具体程序如下:
YHSJPROC
MOVBP,SP
MOVAX,[BP+2];保存N到AX
MOVDX,OFFSETDAT
MOVDA,AX
SHRAX,1;N=N/2
PUSHAX
MOVAX,[BP+2];保存N到AX
PUSHAX
CALLC;C(N,N/2)获取最后一行中间的那个值,即最大值
CALLGETDIGIT;计算该最大值的长度,如252则返回3
MOVCX,AX;保存最大长度到CX,用于事后格式用
XORDI,DI;外层循环计数DI,外层循环输出每一行
JMPCP1
UP1:
INCDI;更新DI
CP1:
CMPDI,[BP+2];测试循环条件,循环N次
JGDONE1
MOVAX,[BP+2];以下3句计算行前空格数=(N-I)*CL,CL是最大长度
SUBAX,DI
MULCL
PUSHBX
MOVBX,DX
MOV[BX],AX
INCDX
INCDX
POPBX
CALLSHOWSPACE;输出行前空格
XORSI,SI;内存循环计数SI,内层循环输出一行中的每个数
JMPCP2
UP2:
INCSI;更新DI
CP2:
CMPSI,DI;测试循环条件,循环DI次
JGDONE2
PUSHSI
PUSHDI
CALLC;获取该行的位于SI位置的组合数,调用C(DI,SI)
PUSHAX;保存该组合数
PUSHBX
MOVBX,DX
MOV[BX],AX
INCDX
INCDX
POPBX
CALLSHOW;输出该数
MOVAX,CX;以下输出数字间间隔空格,个数=N-1
SUBAX,1
PUSHBX
MOVBX,DX
MOV[BX],AX
INCDX
INCDX
POPBX
CALLSHOWSPACE
POPAX
CALLGETDIGIT;获取该组合数长度
MOVBX,AX
MOVAX,CX
SUBAX,BX;计算需要填充的空格数=最大长度-该数长度+1
ADDAX,1
PUSHBX
MOVBX,DX
MOV[BX],AX
INCDX
INCDX
POPBX
CALLSHOWSPACE
JMPUP2;更新内层循环
DONE2:
;内层循环结束
PUSHDX
MOVAH,2;以下5句实现换行
MOVDL,13
INT21H
MOVDL,10
INT21H
POPDX
JMPUP1;更新外层循环
DONE1:
;外层循环结束
RET2;释放函数参数使用的栈空间
YHSJENDP
4.5输出子程序
输出分为上半部分和下半部分,上半部分输出利用2号功能将每个数除以10将余数转化为字符倒序输出,下半部分是将算好的数以及行前行间空格数算好然后倒序输出。
上半部分:
;递归以10进制输出AX
;方法很简单,就是求出余数,然后AX=AX/10
;AX=0时退出,开始逆序输出求出的各位余数
SHOWPROC
PUSHDX
MOVBX,10
CMPAX,0
JZOK1
DIVBL
PUSHAX
ANDAX,00FFH
CALLSHOW
POPDX
MOVDL,DH
ORDL,30H
MOVAH,2
INT21H
OK1:
POPDX
RET
SHOWENDP
MOVAX,DA
INCAL
MOVBL,6
MULBL
SUBDX,AX
DECDX
DECDX
MOVCX,DA
CMPCX,0
JNZL11
MOVAX,1
CALLSHOW
JMPEXIT
L11:
MOVAX,CX
MOVBL,6
MULBL
SUBDX,AX
DECDX
DECDX
MOVBX,DX
MOVAX,[BX]
CALLSHOWSPACE;输出行前空格
PUSHCX
L12:
INCDX
INCDX
MOVBX,DX
MOVAX,[BX]
CALLSHOW;输出该数
INCDX
INCDX
MOVBX,DX
MOVAX,[BX]
CALLSHOWSPACE;输出数字间间隔空格
INCDX
INCDX
MOVBX,DX
MOVAX,[BX]
CALLSHOWSPACE;输出填充的空格
LOOPL12
POPCX
MOVAX,CX
MOVBL,6
MULBL
INCDX
INCDX
SUBDX,AX
DECDX
DECDX
PUSHDX
MOVAH,2;以下5句实现换行
MOVDL,13
INT21H
MOVDL,10
INT21H
POPDX
LOOPL11
EXIT:
MOVDX,OFFSETDATE
MOVAH,9
INT21H
JMPL
课程设计小结
本文主要介绍了利用汇编语言原理技术的一些知识,编写一个能在电脑屏幕上打印杨辉三角的程序代码,不仅能正序输出十阶内的杨辉三角也能倒序输出十阶内的杨辉三角。
我们只是简单的了解了其中一点而已,同时在一些特殊点有较好的输出,但是程序同时存在小的缺点,只能显示到第十三位,因此更应进行深入的研究与探讨。
微机原理程序编写技术也有待于更深入的学习。
参考文献
[1]朱金钧麻新旗.微型计算机原理及应用技术[M](第二版).北京:
机械工业出版社,2005.
[2]王爽.汇编语言[M](第二版).北京:
清华大学出版社,2003.
附录
附录A
程序代码:
datasegment
org100h
messagedb'InputN(N<=10):
$'
errordb0ah,0dh,'Dataoutofrange!
$'
dadw0
datdw300dup(?
)
dataends
codesegment
assumecs:
code,ds:
data
start:
movax,data
movds,ax
movdx,offsetmessage
movah,9
int21h
callshur
cmpbp,10
jbegoon
movdx,offseterror
movah,9
int21h
jmpexit
goon:
movah,2;以下5句实现换行
movdl,13
int21h
movdl,10
int21h
pushbp
callyhsj
movax,da
incal
movbl,6
mulbl
subdx,ax
decdx
decdx
movcx,da
l11:
movax,cx
movbl,6
mulbl
subdx,ax
decdx
decdx
movbx,dx
movax,[bx]
callshowspace;输出行前空格
pushcx
l12:
incdx
incdx
movbx,dx
movax,[bx]
callshow;输出该数
incdx
incdx
movbx,dx
movax,[bx]
callshowspace;输出数字间间隔空格
incdx
incdx
movbx,dx
movax,[bx]
callshowspace;输出填充的空格
loopl12
popcx
movax,cx
movbl,6
mulbl
incdx
incdx
subdx,ax
decdx
decdx
pushdx
movah,2;以下5句实现换行
movdl,13
int21h
movdl,10
int21h
popdx
loopl11
movah,4ch
int21h
exit:
movah,4ch
int21h
shurproc
pushcx
pushbx
xorbp,bp
movbx,10
movcx,2
input:
movah,0;键盘输入数据存在al中
int16h
cmpal,0dh;以回车结束输入
jzok
cmpal,'0';只允许输入0~9
jbinput
cmpal,'9'
jainput
movah,0eh;显示有效输入
int10h
subal,30h;化ASCII为十进制
cbw;字节扩展为字
xchgax,bp
mulbx;扩大10倍
addbp,ax;加一位
loopinput
ok:
nop;数值结果在BP中
;恢复用到的寄存器
popbx
popcx
ret
shurendp
;输出杨辉三角的函数,接受一个栈上的参数N
;输出N阶杨辉三角
yhsjproc
movbp,sp
movax,[bp+2];保存N到ax
movdx,offsetdat
movda,ax
shrax,1;N=N/2
pushax
movax,[bp+2];保存N到ax
pushax
callC;C(N,N/2)获取最后一行中间的那个值,即最大值
callgetdigit;计算该最大值的长度,如252则返回3
movcx,ax;保存最大长度到cx,用于事后格式用
xordi,di;外层循环计数di,外层循环输出每一行
jmpcp1
up1:
incdi;更新di
cp1:
cmpdi,[bp+2];测试循环条件,循环N次
jgdone1
movax,[bp+2];以下3句计算行前空格数=(N-i)*cl,cl是最大长度
subax,di
mulcl
pushbx
movbx,dx
mov[bx],ax
incdx
incdx
popbx
callshowspace;输出行前空格
xorsi,si;内存循环计数si,内层循环输出一行中的每个数
jmpcp2
up2:
incsi;更新di
cp2:
cmpsi,di;测试循环条件,循环di次
jgdone2
pushsi
pushdi
callC;获取该行的位于si位置的组合数,调用C(di,si)
pushax;保存该组合数
pushbx
movbx,dx
mov[bx],ax
incdx
incdx
popbx