微原软件实验报告班级:序号:学号:姓名:实验二分支,循环程序设计一.实验目的:1.开始独立进行汇编语言程序设计;2.掌握基本分支,循环程序设计;3.掌握最简单的DOS 功能调用.二.实验内容:1.安排一个数据区(数据段),内存有若干个正数,负数和零.每类数的个数都不超过9.2.编写一个程序统计数据区中正数,负数和零的个数.3.将统计结果在屏幕上显示.三.预习题:1.十进制数0 -- 9 所对应的ASCII 码是什么? 如何将十进制数0 -- 9 在屏幕上显示出来?答:0—9对应的ASCII码是30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,将十进制数转换成相应的ASCII码并调用字符显示功能即能实现十进制数在屏幕上的显示。
2.如何检验一个数为正,为负或为零? 你能举出多少种不同的方法?答:将该数与0字符(ASCII码为30H)比较,根据比较的结果转入不同的分支。
四.流程图:开始初始化CX,BX,AH,DH,DL[BX] 0?[BX]=0?DH++DH 记录等于零的个数BX++BX++CX--AH++AH 记录小于零的个数DL++DL 记录大于零的个数CX 0?将AH,DH,DL 中的数转成ASCII 码并存储显示结束YES YES NOYESNO NO CX 是待处理的数的个数,BX 是这串数的首地址五.代码:六.运行结果:七.总结:第一次在DOS窗口下用汇编编程,一些基本的操作和以前的高级语言迥然不同,如建立文件,编译,链接,调试,这些操作都是要在DOS窗口中键入语言指令来完成的,不像高级语言的编译器只要按下相关的键就好了,用语言指令能更加明白编译,调试这些操作真正的含义。
更重要的是调试指令,通过这些指令,可以直接看到寄存器,内存中真真切切的变化,对硬件的工作机制特别是cpu的指令运行,内存的数据存储与读取,整个程序运行的本质过程有了更加透彻的了解和认识。
在本次实验中,主要对顺序结构,分支结构以及循环结构有了初步的运用,程序编写的关键是流程图,当对题目有了分析并且设计出了条理清晰,步骤较为详细的流程图之后,只要对照图写就很快:顺序执行下来的地方用顺序结构,有判断的地方用分支结构,有循环执行的地方用循环结构,整个程序的框架就构建完成,剩下的就是变量、寄存器以及内存空间的读写了。
实验三代码转换程序设计一.实验目的:1.掌握几种最基本的代码转换方法;2.运用子程序进行程序设计.二.实验内容:1.从键盘上输入若干两位十进制数,寻找其中的最小值,然后在屏幕上显示出来.2.两个十进制数之间的分隔符,输入结束标志自定,但要在报告中说明.3.对输入要有检错措施,以防止非法字符输入,并有适当的提示.4.将整个程序分解为若干模块,分别用子程序实现.在报告中要给出模块层次图.三.预习题:1.如何将输入的两个字符(0 -- 9)变为十进制或二进制数?答:因为输入的字符是以ASCCII码(8位二进制)表示的,所以分别对两个字符做减30H 的操作,再将先输入的字符作为十位,后输入的字符为个位即可得到相应十进制的二位数。
2.如何将选出的最小值(二进制或十进制)变为ASCII 码再进行显示?答:将选出的十进制最小值加上30H即变成了对应的ASCII码,将这个值的十位和个位先后存储在DL中,先后两次使用AH=02H功能输出整个两位十进制数。
但是其实在数的存储和输出时不需要进行ASCII码与十进制数的转换,直接对ASII码的大小比较即可。
3.你觉得采用二进制运算还是十进制运算更适合于这个实验?答:正如上面题中所说,直接用二进制运算对于这个实验来说更加方便和简单。
四.流程图:开始输入二位数的十位将键盘输入的数存入BH 是否在0~9?YES输入二位数的个位是否在0~9?将键盘输入的数存入BL 按下回车?比较最后输入的二位数与MIN 的大小BX MIN?将MIN 中的数打印显示NO更新MIN 的值即MIN=BX结束NO提示输入错误NO按下空格?比较BX 与MIN 的大小BX MIN ?更新MIN 的值即MIN=BXNONOYESNOYESYESYESYES五.模块层次图:输入模块检验模块显示模块比较模块主程序循环七.运行结果:结果说明:第一次运行,输入正确,按下回车就会显示输入数字中的最小值。
第二次运行,输入了不是0~9的字符$则提示输入错误,重新输入,再次输入时输入了一个三位数,又会提示输入错误。
八.总结:本次实验和上个实验一样还是要比较数之间的大小关系,只不过这次要求更高:待比较的对象都是从键盘输入,且每次的比较的两个对象不是固定的,比较完成后需要将比较的两个对象之一写入固定的变量中。
分析完程序要求后还是写流程图,写的过程中就会发现功能其实是要多次调用的,如输入模块,检验模块。
比较大小及更新最小值的部分在一次循环中只需要执行一次,可以不用子程序的形式,不过为了程序看起来更加有层次感和模块化,我将比较和显示也分别写成了子程序的形式,这样主程序看起来就更加简洁明了。
这次对子程序的使用让我更加清楚了子程序的实质,其实它就是一段在别处封装好的具有一定功能实现的代码段,当call它的时候就转到子程序所在的地址执行,遇到RET时再返回到调用的断点处,这是与转移指令有本质区别的地方,转移指令是“一去不回”,而子程序是“有去有回”。
实验四子程序设计一.实验目的:1.进一步掌握子程序设计方法;2.进一步掌握基本的DOS 功能调用.二.实验内容:1.从键盘上输入某班学生的某科目成绩.输入按学生的学号由小到大的顺序输入.2.统计检查每个学生的名次.3.将统计结果在屏幕上显示.4.为便于观察,输入学生数目不宜太多,以不超过一屏为宜.输出应便于阅读.尽可能考虑美观.5.输入要有检错手段.三.预习题:1.如何确定一个学生在这门科目中的名次?答:对输入的成绩进行排序,并且较大数存在低地址,较小的数存在高地址。
2.你觉得输入结束后,采用什么方法进行比较以得到学生的名次最为简单?答:在对成绩进行排序和改变其在内存中的存储位置的同时将每个成绩对应的序号用同样的方法改变序号在内存中的存储位置,这样将排序后的序号连续读出来就能得到所有序号对应学生在这门科目中的名次。
3.准备好模块层次图.输入模块检验模块存储模块冒泡排序模显示模块块4.给出输出显示的形式.排名:1 2 3 4 5 …..序号:(与下面的成绩对应)成绩:(从高到低排列)四.流程图:开始输入十位0~9?存储在高位输入个位YES0~9?YES存储在低位输入回车?输入空格?NO错误提示YESCL=0[SI+DL*2] [SI+DL*2+2]?YES CL++CL=COUNT1?YESCOUNT1--COUNT1>0?NO显示名次显示序号显示成绩结束NO NOCL 是内循环的计数器SI 指向成绩序列的首地址,DL=CL 内循环计数器加一[SI+DL*2]与[SI+DL*2+2]交换[SI+DL]与[SI+DL+2]交换SI 指向成绩序列首地址,DL=CLSI 指向序号序列首地址,DL=CLCOUNT1是每次内循环需要进行的内循环的次数NO YESYES六.总结:本次实验可以分为三大块,一是输入及存储,二是排序,三是显示,在第一部分中很多是上个实验已经实现的功能,唯一不同的地方是这次需要将每次输入的数据有序的存在一段连续的内存中,以便输入结束后能对这段内存中的数进行排序。
排序模块需要对排序算法有较为透彻的理解,这里采用冒泡排序,减小时间复杂度,和高级语言中的冒泡排序不同的是,这里要对数据所在的地址有非常清晰的认识,这样才能有序的进行两数的比较以及比较完毕可能会有的数据交换。
显示部分相对来说就比较简单了,用地址加的方式对相应字符串中的字节进行显示即可。
在这次实验中,让我最受益匪浅的是,在算法设计及数据读写的过程中数据所在地址的变化,这经常让我转晕了,所以就得在纸上画出内存及其地址的示意图来帮助我。
整个程序下来对硬件中内存地址的分配和数据的存储有了更加清晰的认识。
实验五中断程序设计一.实验目的:1.初步掌握中断程序的设计方法:2.初步掌握修改DOS 系统中断,以适应实际使用的方法.二.实验内容:1.编写一个32 位二进制数除以16 位二进制数的除法程序.观察当除数为0,或超过相应寄存器范围时,程序执行的结果.2.修改零号中断服务程序,使它具有以下功能:(1)判断除数是否为0,当除数为0 时,显示相应的结果;(2)当除数不为0 时,采用适当的方法完成商超过16 位的二进制数的除法运算.3.注意必须保护原有中断服务程序的入口地址,并在程序完毕前加以恢复.三.预习题:1.如何保护原有中断向量表中的中断服务程序的入口地址?答:在主程序一开始就将原终端服务程序的入口地址压栈保存。
2.如何将你的中断服务程序入口地址置入中断向量表?答:用直接写入的方法,将我的中断服务子程序的段地址和偏移地址赋给ES:[0002H]和ES:[0000H]四.选作题:1.用二进制将结果在屏幕上显示.2.从键盘输入二进制数.五.流程图:开始键盘输入将键盘的输入转化成二进制存储做除法溢出?YES进入0号中断除数等于零?NO扩展除法结果显示结束YES Error,退出dosNO六.代码:七:运行结果:(a)(a)图是当除数为零的时候报错,并退出DOS。
(b)(b)图是当商没有超过16位时,但是程序有问题,商的计算完全正确,但是余数却是错误的,仔细检查了ASCII码和16二进制的相互转换,并没有发现问题,而且商和余数是调用的同一个转换子程序,如果转换有问题那么商也会出错。
光看代码找不出错误后我开始调试,想看看没有溢出的时候除法计算后的商和余数是否正确,先用u命令查看了DIV BX 的地址,然后用g=0000 00d3将程序执行到DIV BX处,如下图(c)所示,当执行完DIV BX 后,AX=8000(存储商),DX=0000(存储余数),计算结果完全正确,但是继续往下实行到下图(d)中所示的红线时,出现了一条我并没有编写的程序JZ,遗憾的是当我想继续跟踪执行的时候调试出问题了,g命令和t命令都不能正常使用了,所以目前只能进行到这一步了,不过在验收之前我还会继续调试,努力找出问题所在的。
(c)(d)(e)图(e)是商超过16位时的扩展32位除法,商高16位是正确的,低16为和余数不对,而且余数和图(b)中的一样,我试过很多数,大多数情况下的余数都是这个值,肯定是哪里程序对正确的余数改动了我却不知道。
八.总结:这个程序主要是练习中断向量表的写和读,关键的就是原向量表的保存和恢复以及新向量表中的中断子程序地址的写入。
书上介绍了两种方法:直接写入法和用DOS提供的功能号完成,我个人比较喜欢前者,因为更加直观和直接。