微机原理课程设计——汇编输出杨辉三角.docx
微机原理课程设计汇编输出杨辉三角 目录 第一章绪论 (1) 第二章分析与设计 (2) 2.1 题目 (2) 2.2 要求 (2) 2.3 方案设计与论证 (3) 2.3.1 整体设计思路 (3) 2.3.2 方案选择 (3) 2.4 结构框图 (4) 3.1 宏定义换行 (5) 3.2 阶数输入过程 (5) 3.3 数据判断功能 (6) 3.4 询问继续模块 (7) 3.5 数值计算模块 (7) 3.6 显示模块 (9) 3.6.1 数据显示 (9) 3.6.2 空格显示 (10) 第四章实验结果及问题处理 (12) 4.1 实验结果 (12) 4.2出现的问题以及解决的方案 (13) 4.2.1 数据输入问题 (13) 4.2.2 除法溢出问题 (13) 4.2.3 数据计算问题 (14) 第五章总结与体会 (15) 参考文献 (17) 附录 (18) 第一章绪论 随着电子计算机技术的不断发展,微型计算机系统的功能越来越强,而关于计算机的程序设计语言也经历了一个发展的过程。从最基本的机器语言到汇编语言,并发展到高级的智能化语言,如visual C+、Visual Basic等。 汇编语言(Assembly Language)是一种采用助记符表示的程序设计语言,即用助记符来表示指令的操作码和操作数,用符号或标号代表地址、常量或变量。助记符一般都是英文单词的缩写,便于识别和记忆。使用汇编语言编写的程序称为汇编语言源程序。汇编语言源程序不能由机器直接执行,而必须翻译成有机器代码组成的目标程序,这个翻译的过程称为汇编。把汇编语言源程序翻译成目标程序的软件称为汇编程序。 汇编语言与机器语言密切相关,它们之间有明显的对应关系。一条汇编语言指令对应一条机器语言代码,所以汇编语言和机器语言一样都是面向机器的语言。使用汇编语言进行程序设计能充分利用机器的硬件功能和结构特点,从而有效地加快程序的执行速度,减少程序占用的存储空间。所以汇编语言大量用于编写计算机系统程序、实时通信程序和实时控制程序等。 汇编语言作为最基本的编程语言之一,汇编语言虽然应用的范围不算很广,但重要性却勿庸置疑,因为它能够完成许多其它语言所无法完成的功能。就拿Linux内核来讲,虽然绝大部分代码是用C语言编写的,但仍然不可避免地在某些关键地方使用了汇编代码,其中主要是在Linux的启动部分。由于这部分代码与硬件的关系非常密切,即使是C语言也会有些力不从心,而汇编语言则能够很好扬长避短,最大限度地发挥硬件的性能。 第二章分析与设计 2.1 题目 汇编显示杨辉三角 2.2 要求 基本内容:在提示信息下,从计算机键盘输入一个满足要求的数据,在输出提示信息后显示相应的杨辉三角。 具体要求如下: (1)要有提示信息的输出显示,例如程序执行时直接显示输出提示信息“Please input a number:”然后等待用户从计算机键盘输入具体数值,例如输入“4”,然后换行显示下一步提示信息,例如“The YangHui triangle:”最后显示通过程序获得的杨辉三角如下: (2)分析杨辉三角具体算法,计算结果要求正确。输出的杨辉三角要求上下左右对称显示,上下分别为两个等腰三角形的形式,即要求分析总结每行行首空格数量,及三角中各个数之间空格的安排方法; (3)要求最少要能够输出10阶的杨辉三角; (4)提高要求:增大阶数(最少到20阶),可任意选择正反三角显示。 2.3 方案设计与论证 2.3.1 整体设计思路 本课题要求用汇编显示杨辉三角形,首先得了解什么是杨辉三角形。杨辉三角形,又称贾宪三角形,帕斯卡三角形,是二项式系数在三角形中的一种几何排列。其每一行的数据都有其特定的规律,杨辉三角形又有其独特的性质:1、每行数字左右对称,由1开始逐渐变大,然后变小,最后回到1。2、第n行的数字个数为n个。3、第n行数字和为2(n 1)。4、每个数字等于上一行的左右两个数字之和,故可用此性质写出整个帕斯卡三角形。 5、第n行的第1个数为1,第二个数为1×(n-1),第三个数为1×(n-1)×(n-2)/2,第四个数为1×(n-1)×(n-2)/2×(n-3)/3···依此类推。 在熟悉了杨辉三角形的产生原理,杨辉三角形内各数据的计算方法之后,再在掌握了相关汇编知识以及一定编程能力的基础上,我们对课题进行了相关分析,总体来说,这个课题的关键点分为以下部分,厘清这些关键点也是作为明确整体设计思路的重要过程: (1)、提示信息的显示。题目明确要求显示中要有提示信息,实际上,根据需要,在本课题中我们又加了一些功能,当然也必须要增加额外的提示信息。 (2)、阶数的输入功能。通过DOS系统功能调用,确定需要显示杨辉三角形的行数与大小,能够实现简单的人机交互。 (3)、编程得到需要在杨辉三角中显示的数。基于以下思想:第n行的第1个数为1,第二个数为1×(n-1),第三个数为1×(n-1)×(n-2)/2,第四个数为1×(n-1)×(n-2)/2×(n-3)/3···依此类推。 (4)、某数的显示及换行。为了显示的规范和美观,必须考虑到数与数之间的空格数,当然,某数的显示是能够完整输出杨辉三角形的基础和前提。 (5)、新增功能,判断输入数据是否满足条件,判断是否继续执行。考虑到本程序的使用范围及使用者能连续使用显示杨辉三角形的方便性,特增加了数据判断和询问继续功能,使用者想要继续执行即输入“Y”,程序自动从头开始执行,若输入“N”,则退出。 2.3.2 方案选择 1. 对于阶数输入功能,我们想到两种方案。 方案(1):参考相关文献上得知,可以通过DOS系统功能调用:键盘输入单字符1 号系统功能调用,同时实现字符的输入与显示。 调用格式:MOV AH,1 INT 21H 说明:1号功能调用无入口参数,执行时系统首先等待键盘输入,待程序员按下任何一键,系统先检查是否是Ctrl-Break键。如果是则退出,否则将键入的字符的ASCII码置入AL 寄存器,并在屏幕上显示该字符。 方案(2):同样是DOS系统功能调用,键盘输入字符串0AH号系统功能调用。 说明:其功能是将键盘输入的字符串写入到内存缓冲区,因此调用之前必须事先定义一个缓冲区。缓冲区的第一个字节给出用来存放键入的字符数,第二个留给系统填写实际键入的字符个数,从第三字节开始用来存放键入的字符串,最后键入回车( )键表示字符结束。 对于方案(1),格式简单,使用方便,易于理解,但是对于输入多位数,相对有点复杂。对于方案(2),从实际编程水平出发,不太能够娴熟的使用该系统功能,调用格式复杂,而且鉴于该程序输入的位数不超过两位,所以我们最后选择了方案(1)。 2.4 结构框图 在编写程序之前,明确其整个思路的流程图是相当重要的,所以我们花了一些时间来画出流程图,根据流程图来写实际程序。如图2.4.1为本程序的总体汇编思路图。 图2.4.1 程序总体流程图 第三章实验程序及分析 3.1 宏定义换行 为了简化汇编语言源程序,可以把一些频繁出现的程序段定义为“宏指令”,当遇到这段程序时,只要按宏指令名调用即可,不必重复写许多指令,汇编程序在遇到宏指令时将其期待成相应的代码,这样就有效地缩短汇编语言源程序的长度,使源程序易读,也减少了由于重复书写而引起的错误。在本课题中,为了显示杨辉三角,必然需要多次使用换行代码,故将换行代码定义为“宏指令”,有以上所述的诸多好处。宏定义如下:HUANH MACRO ; 宏名为HUANH MOV AH, 2 ; 使用2号功能,显示器输出字符 MOV DL, 13 ; 13即ASCII为0DH是回车符 INT 21H ; DOS系统功能调用 MOV DL, 10 ; 10即ASCII为0AH是换行符 INT 21H ; DOS系统功能调用 ENDM ; 宏定义结束 3.2 阶数输入过程 过程是程序的一部分,它可以被程序调用。每次可调用一个过程,当过程中的指令执行之后,控制返回调用它的地方。过程的定义是用过程定义伪指令完成的。过程的定义有三个注意点:、过程名是自定义符,定义开始和结束时的过程名必须相同。、过程名有三个属性:段地址,偏移量和距离属性(NEAR和FAR),汇编程序在汇编时根据过程类型生成段内或段间的调用或返回指令代码。、在一个过程中,可以有多个RET指令。一个过程总是通过RET指令返回,RET常作为过程的最后一条指令。在了解以上说明及注意点的基础上,我们根据实际需要定义了一个实现阶数输入功能的过程。具体定义如下:SHURU PROC ; 输入过程定义,数字存在BP XOR BP,BP MOV BX,10 MOV CX,3 ; 控制输入位数,外加一位回车 input: MOV AH,1 ; DOS功能调用,键盘输入和显示数据 INT 21H CMP AL,0DH ; 判断是否以回车结束输入 JZ OK SUB AL,30H ; 将ASCII码转为16进制数 CBW ; 字节扩展为字,为了下一条交换指令 XCHG AX,BP MUL BX ; 扩大10倍 ADD BP,AX ; 加一位 LOOP input OK: RET ; 返回调用过程的地方 SHURU ENDP ; 过程定义结束 3.3 数据判断功能 在第一套程序编写完毕,试运行时,我们发现,本程序能够支持输入的数据最大值为14,当数据大于等于15时,则程序出现除法溢出问题,并且自动关闭,所以为了能让使用者不至于输入不合法的数据,我们特增加了数据判断功能,输入数据满足条件,允许执行。否则,提示输入数据超过范围,要求重新输入。程序段如下: MAIN: MOV DX,OFFSET MSG ; 输出字符串,请输入一个数 MOV AH,9 ; 9号功能调用,输出字符串 INT 21H CALL SHURU ; 调用输入函数,显示输入的数 CMP BP,15 ; 输入的数存在BP,与15比较 JB MZTJ ; 满足条件,允许执行 HUANH ; 否则换行 MOV DX,OFFSET ERROR ; 准备显示错误信息 MOV AH,9 INT 21H HUANH ; 继续换行 JMP MAIN ; 无条件跳转到MAIN,重新开始 MZTJ: HUANH ··· ··· ··· 3.4 询问继续模块 在首套程序编写完毕运行时,每次我们只能运行一次显示杨辉三角的程序,以后还得重新键入相关命令,才能运行,如此调试程序,效率低下,且可能混乱我们对现象的记录。所以考虑到我们调试程序的高效性及对于使用者的便利性,我们又增加了一个询问继续模块,当第一次杨辉三角显示完毕,提示是否继续,如果键入“Y”,则程序自动重新开始执行;如果键入“N”,则程序运行结束,退出。程序段如下: input1: HUANH MOV DX,OFFSET CON ; 显示提问字符串,继续? MOV AH,9 INT 21H ; 判断是否继续 MOV AH,1 ; 键盘输入数据 INT 21H CMP AL,59H ; 判断输入的是否是Y JNZ exit1 HUANH JMP NEAR PTR MAIN ; 段内直接近转移,可以转移到段内的任何一个位置 exit1: MOV AH,4CH ; 结束程序,返回DOS INT 21H 3.5 数值计算模块 本段数值计算,是正确显示杨辉三角的关键,所以能否找到一种既简便又能保证计算正确性的方法,是我们本阶段工作的中心,我们参阅了很多资料,从几种计算方法中,选取了最符合我们实际编程水平的,又在保证计算正确性的基础上,写出了如下的程序段,它的思想是基于:第n行的第1个数为1,第二个数为1×(n-1),第三个数为1×(n-1)× (n-2)/2,第四个数为1×(n-1)×(n-2)/2×(n-3)/3···依此类推。 如图3.5.1为本段程序的流程图,文字描述即为上段。 图3.6.1 数值计算流程图Calculate:DEC b ; b每次减1相乘 MUL b DIV c ; 除以c,再加1 INC c CMP b,0 ; b是否为0 JZ ok1 PUSH AX ; 保存所得数据 MOV d,0 ; 此处d为位数,为了显示后面的空格 CALL ShowNum MOV AX,6 ; 预设,总共显示的空格数为6个单位 SUB AX,d ; 还需显示多少空格 CALL Showspace1 POP AX CALL Calculate ; 继续执行 ok1:RET 3.6 显示模块 3.6.1 数据显示 得到杨辉三角中的某一个数后,接下来的任务就是如何将它显示出来。不能完成这项工作,就不能完成整个课题。我们小组在参考平时微机实验的基础上,自己分析,找到了一种正确的显示方法:可以将某数不断除以10,取出余数显示,直到商为0,停止除法。例如:要显示的数是345,除以10后,商为34,余数为5,5压入堆栈。然后将34除以10,商为3,余数为4,4压入堆栈。最后将3除以10,商为0,余数为3,3压入堆栈。弹出堆栈,依次显示,在汇编中,使用无符号数除法指令DIV OP。指令DIV BL,被除数存在AX中,整数商存在AL,余数存在AH。所以在除以10后,只需将AH中的值取出,下一次除法,可以用逻辑指令AND将其高八位屏蔽,调用2号功能,依次显示。 为了能充分体现我们编程的思想,如图3.6.1是数据显示部分的流程图,以下编写的程序也是基于这种思想。 图3.6.1 数据显示流程图 具体程序段如下: ShowNum: MOV BX, 10 ; BX中存除数10 CMP AX, 0 ; 除法运算是否完毕 JZ ok2 INC d ; 此处d为位数,以确定输出的空格数 DIV BL ; 除以10,整数商存在AL,余数存在AH PUSH AX AND AX, 00FFH ; 屏蔽高八位,取商 CALL SHOWNum POP DX MOV DL, DH ; 取出高八位,即为要显示的余数 OR DL, 30H ; 转为ASCII码 MOV AH, 2 INT 21H ok2: RET 3.6.2 空格显示 空格的显示,是为了调整整体杨辉三角的布局,使其输出为美观的等腰三角形。前期,我们采用在方格纸上试书写的方式,确定需要显示的空格数。实际编程中,使用到了3中空格形式,第一种是首数字1之前的空格,定义为AHEAD,第二种是首数字1后面的空格,定义为BETWEEN,第三种是和需显示的数字位数相关的空格,定义为BACK,具体在程序中定义如下:AHEAD DB ' $' BETWEEN DB ' $' BACK DB ' $' 定义了这三种空格后,需要将其显示,这里我们使用DOS功能调用,9号系统功能调用输出字符串。功能是将指定的内存缓冲区中的字符串在屏幕上显示出来,缓冲区的字符串以“$”为结束标志。 Showspace: MOV BX, AX ; 首行显示空格,空格数即为输入的阶数 MOV AH, 9 MOV DX,OFFSET AHEAD nexts: CMP BX, 0 ; BX减1,控制输出的空格数 JZ dones