211122班+李济汉+10210737+20号+微机原理软件实验报告终版.docx
《211122班+李济汉+10210737+20号+微机原理软件实验报告终版.docx》由会员分享,可在线阅读,更多相关《211122班+李济汉+10210737+20号+微机原理软件实验报告终版.docx(38页珍藏版)》请在冰豆网上搜索。
211122班+李济汉+10210737+20号+微机原理软件实验报告终版
2012年微机原理软件实验报告
学院:
信息与通信工程学院
班级:
2010211122
姓名:
李济汉
学号:
10210737
班内序号:
20
实验二分支及循环程序设计
一、实验目的
1、开始独立进行汇编语言程序设计;
2、掌握基本分支,循环程序设计;
3、掌握最简单的DOS功能调用。
二、实验内容
1、安排一个数据区,内存有若干个正数,负数和零.每类数的个数都不超过9;
2、编写一个程序统计数据区中正数,负数和零的个数;
3、将统计结果在屏幕上显示。
三、程序流程图
四、实验原理
1、判断正负数:
通过与0进行大小比较,与0相等的为0,大于0的为正数,小于0的为负数。
2、判断奇偶性:
首先将16位数的最后一位取出,与0进行比较,若为0则该数必为偶数,若为1则该数必为奇数。
3、计数:
利用不同寄存器存放不同类数的计数值,最后将其赋入相应变量名中。
五、实验源程序(包括选做题)
1、在只求正负数个数时:
DATASEGMENT
BUFFDW2,3,-4,-5,-6,-7,5,0,7,0,-2,-4,9;设置数字
COUNTEQU$-BUFF;记录数字个数(2倍)
PLUSDB?
ZERODB?
MINUSDB?
THREAD1DB'Theresultis:
',0DH,0AH,'Numberof0:
$';显示0的个数
THREAD2DB0DH,0AH,'Numberabove0:
$';显示正数的个数
THREAD3DB0DH,0AH,'Numberbelow0:
$';显示负数的个数
DATAENDS
STACKSEGMENTSTACK'STACK'
DW100DUP(?
)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,ES:
DATA,SS:
STACK
STARTPROCFAR
PUSHDS;初始化各段
XORAX,AX
PUSHAX
MOVAX,DATA
MOVDS,AX
MOVAX,STACK
MOVSS,AX
MOVCX,COUNT
SHRCX,1;右移一位,相当于除以2,得到数字个数
MOVDX,0;利用DH记录0的个数,DL记录正数个数
MOVAH,0;利用AH记录负数个数
LEABX,BUFF
AGAIN:
CMPWORDPTR[BX],0
JGEPLU
INCAH;若为负数,则AH递增
JMPNEXT
PLU:
JZZER
INCDL;若为正数,则DL递增
JMPNEXT
ZER:
INCDH;若为0,则DH递增
NEXT:
INCBX;跳至下一个数字
INCBX
LOOPAGAIN
MOVBH,0
MOVBL,DL
ADDBX,'0';将正数个数转化为ASCII码
MOVPLUS,BX
MOVBH,0
MOVBL,DH
ADDBX,'0';将0的个数转化为ASCII码
MOVZERO,BX
MOVBH,0
MOVBL,AH
ADDBX,'0';将负数个数转化为ASCII码
MOVMINUS,BX
MOVAH,09H;显示提示信息
MOVDX,SEGTHREAD1
MOVDS,DX
MOVDX,OFFSETTHREAD1
INT21H
MOVAH,02H
MOVDL,ZERO;显示0的个数
INT21H
MOVAH,09H
MOVDX,SEGTHREAD2
MOVDS,DX
MOVDX,OFFSETTHREAD2
INT21H
MOVAH,02H
MOVDL,PLUS;显示正数的个数
INT21H
MOVAH,09H
MOVDX,SEGTHREAD3
MOVDS,DX
MOVDX,OFFSETTHREAD3
INT21H
MOVAH,02H
MOVDL,MINUS;显示负数的个数
INT21H
MOVAX,4C00H
INT21H
STARTENDP
CODEENDS
ENDSTART
2、在求正负奇偶数个数时:
DATASEGMENT
BUFFDW2,3,-4,-5,-6,-7,5,0,7,0,-2,-4,9
COUNTEQU$-BUFF
PLUSODDDB?
;存放正奇数
PLUSEVENDB?
;存放正偶数
ZERODB?
;存放0
MINUSODDDB?
;存放负奇数
MINUSEVENDB?
;存放负偶数
THREAD1DB'Theresultis:
',0DH,0AH,'Numberof0:
$';显示0的个数
THREAD2DB0DH,0AH,'Numberofoddsabove0:
$';显示正奇数个数
THREAD3DB0DH,0AH,'Numberofevensabove0:
$';显示正偶数个数
THREAD4DB0DH,0AH,'Numberofoddsbelow0:
$';显示负奇数个数
THREAD5DB0DH,0AH,'Numberofevensbelow0:
$';显示负偶数个数
DATAENDS
STACKSEGMENTSTACK'STACK'
DW100DUP(?
)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,ES:
DATA,SS:
STACK
STARTPROCFAR
PUSHDS
XORAX,AX
PUSHAX
MOVAX,DATA
MOVDS,AX
MOVAX,STACK
MOVSS,AX
MOVCX,COUNT
SHRCX,1
MOVSI,0;存0的个数
MOVDX,0;高位存正偶数的个数,低位存正奇数的个数
MOVBX,0;高位存负偶数的个数,低位存负奇数的个数
LEADI,BUFF
AGAIN:
CMPWORDPTR[DI],0;与0比较,得到正负
JZZER;若等于0,则跳到零
JGPLUS1;若大于等于0,则跳到正
MOVAX,WORDPTR[DI]
ANDAX,0001H;取出最低位
CMPAX,0;若最低位为1,则为奇数
JZMINUS;若最低位为0,则为偶数
INCBL;负奇数加一
JMPNEXT
MINUS:
INCBH;负偶数加一
JMPNEXT
PLUS1:
MOVAX,WORDPTR[DI]
ANDAX,0001H;取出最低位
CMPAX,0
JZPLUS2
INCDL;正奇数加一
JMPNEXT
PLUS2:
INCDH;正偶数加一
JMPNEXT
ZER:
INCSI;零加一
NEXT:
INCDI
INCDI
LOOPAGAIN
PUSHSI;保护SI的值,防止程序改写的SI值影响最终结果
MOVCH,0
MOVCL,DL
ADDCX,'0'
MOVPLUSODD,CX;将各类数的记录值分别赋予不同的变量名
MOVCH,0
MOVCL,DH
ADDCX,'0'
MOVPLUSEVEN,CX
POPAX
MOVCH,0
MOVCL,LOWAX
ADDCX,'0'
MOVZERO,CX
MOVCH,0
MOVCL,BL
ADDCX,'0'
MOVMINUSODD,CX
MOVCH,0
MOVCL,BH
ADDCX,'0'
MOVMINUSEVEN,CX
MOVAH,09H;显示字符串
MOVDX,SEGTHREAD1
MOVDS,DX
MOVDX,OFFSETTHREAD1
INT21H
MOVAH,02H
MOVDL,ZERO;显示0个数
INT21H
MOVAH,09H
MOVDX,SEGTHREAD2
MOVDS,DX
MOVDX,OFFSETTHREAD2
INT21H
MOVAH,02H
MOVDL,PLUSODD;显示正奇数个数
INT21H
MOVAH,09H
MOVDX,SEGTHREAD3
MOVDS,DX
MOVDX,OFFSETTHREAD3
INT21H
MOVAH,02H
MOVDL,PLUSEVEN;显示正偶数个数
INT21H
MOVAH,09H
MOVDX,SEGTHREAD4
MOVDS,DX
MOVDX,OFFSETTHREAD4
INT21H
MOVAH,02H
MOVDL,MINUSODD;显示负奇数个数
INT21H
MOVAH,09H
MOVDX,SEGTHREAD5
MOVDS,DX
MOVDX,OFFSETTHREAD5
INT21H
MOVAH,02H
MOVDL,MINUSEVEN;显示负偶数个数
INT21H
MOVAX,4C00H
INT21H
STARTENDP
CODEENDS
ENDSTART
六、实验运行结果
程序中存储的数据为:
2,3,-4,-5,-6,-7,5,0,7,0,-2,-4,9
在只求正负数个数时:
在求正负奇偶数个数时:
七、思考题
1、十进制数0--9所对应的ASCII码是什么?
如何将十进制数0--9在屏幕上显示出来?
答:
十进制数0--9所对应的ASCII码是30H,31H,32H,33H,34H,35H,36H,37H,38H,39H。
对应的ASCII码赋给DX,用02号功能调用即可。
代码如下:
MOVAH,02H
MOVDL,ASCII
INT21H
2、如何检验一个数为正,为负或为零?
你能举出多少种不同的方法?
答:
将该数与0作比较(CMP),检验其ZF位,若ZF=1则该数为0;再检验其SF位,若SF=0,则该数为正数;若SF=1,则该数为负数。
将该数与FFFFH相加,首先检验CF值,若CF=1则该数为正数,接下来检验结果,若结果仍为FFFFH,则该数为0,否则该数为负数。
将该数与0作比较(CMP),直接判断结果,若结果等于0则该数为0,若结果大于0,则该数为正数;若结果小于0,则该数为负数。
八、实验总结、问题分析、心得体会
经过这次实验,我对汇编语言的编程有了进一步体会,首先我对DOS运行环境更加熟悉了,对debug的各种执行选项有了了解,能够逐步地进行调试了,这对于我将来设计大的汇编程序有很大帮助。
在理论上,我更加清楚地理解了基本分支与循环程序的设计的方法与步骤,并进行了成功的实践;同时我对基本输入输出控制指令也有了更深入的了解与实现。
在实验过程中,我遇到了一个问题:
即输出奇偶数个数总是判断不准确的问题。
一开始我查看了所有代码与执行流程,但并没有发现逻辑错误,于是我开始单步调试,最终终于发现了一个隐藏错误,即在使用寄存器SI计数后,在其他部分中系统有过对SI寄存器的自动修改,因此最终计数值不对。
于是,我将计数值首先存入堆栈,然后在输出时再返回寄存器显示。
这样就避免了计数错误的问题。
可以说,我在本次实验上学到了很多。
实验三代码转换程序设计
一、实验目的
1、掌握几种最基本的代码转换方法;
2、运用子程序进行程序设计。
二、实验内容
1、从键盘上输入若干两位十进制数,寻找其中的最小值,然后在屏幕上显示出来。
2、两个十进制数之间的分隔符,输入结束标志自定,但要在报告中说明。
3、对输入要有检错措施,以防止非法字符输入,并有适当的提示。
4、将整个程序分解为若干模块,分别用子程序实现。
在报告中要给出模块层次图。
三、程序流程图与程序模块图
四、实验原理
首先进行输入正误的判断,若不为0-9中的数字,将会跳转至报错子程序;每次需要输入两位数,分别作为十位数与个位数,每输入一个数字则进行一次判断,并且将数字分别与最小值存储的数据进行比较,若小于存储值,则调用子程序将当前值作为新的最小值放入存储单元中,比较时利用字符ASCII码值的大小进行比较,这与0-9的大小关系是一样的。
最后输出时依然调用子程序输出。
五、实验源程序
DATASEGMENT
OUTPUTDB0DH,0AH,'Inputyourdecimalnumbers(separatedby,endedby;):
',0DH,0AH,'$';输入信息
ERRORDB0DH,0AH,'InputError!
',0DH,0AH,'$';错误信息
DISPLAYDB0DH,0AH,'theMinimumis:
',0DH,0AH,'$';输出信息
MINIMUMDB'9','9';首先将存放最小值的变量赋为99,使得第一次比较能够正确进行
DATAENDS
STACKSEGMENTSTACK'STACK'
DB100DUP(?
)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
INPUTPROCNEAR;显示输入提示子程序
MOVAH,09H
MOVDX,OFFSETOUTPUT
INT21H
RET
INPUTENDP
ILLEGALCALLPROCNEAR;显示错误信息子程序
MOVDX,OFFSETERROR
MOVAH,09H
INT21H
RET
ILLEGALCALLENDP
ILLEGAL:
CALLILLEGALCALL
JMPLOOP1;重新输入
REWRITECALLPROCNEAR;对最小值进行更新子程序
MOVWORDPTRMINIMUM,DX
RET
REWRITECALLENDP
REWRITE:
CALLREWRITECALL
JMPLOOP2
FORWARDCALLPROCNEAR;显示输出信息子程序
MOVAH,09H
MOVDX,OFFSETDISPLAY
INT21H
MOVAH,02H
MOVDL,MINIMUM+1;显示最小值的十位数
INT21H
MOVAH,02H
MOVDL,MINIMUM;显示最小值的个位数
INT21H
RET
FORWARDCALLENDP
START:
MOVAX,DATA
MOVDS,AX;数据段初始化
LOOP1:
CALLINPUT
LOOP2:
MOVAH,01H;输入十位数并判断其合法性
INT21H
CMPAL,'0'
JBILLEGAL
CMPAL,'9'
JAILLEGAL;若不满足输入数字为0-9,则提示错误
MOVDH,AL;将十位数存入DH中
MOVAH,01H;输入个位数并判断其合法性
INT21H
CMPAL,'0'
JBILLEGAL
CMPAL,'9'
JAILLEGAL;若不满足输入数字为0-9,则提示错误
MOVDL,AL;将个位数存入DL中
MOVAH,1
INT21H
CMPAL,';';若输入的是结束符“;”则输入比较结束,进入输出子模块
JZFORWARD
CMPAL,',';若输入的不是分隔符“,”则提示错误
JNZILLEGAL
CMPDX,WORDPTRMINIMUM;若与最小值比较后小于最小值,则用该值刷新最小值,否则不对最小值进行改动
JBREWRITE
JMPLOOP2
FORWARD:
CALLFORWARDCALL
MOVAX,4C00H
INT21H
CODEENDS
ENDSTART
六、实验运行结果
本实验中设置的输入分隔符为“,”,结束符为“;”,以“InputError!
”作为错误提示。
判断规则是:
当输入的数字不为两位数字或者分隔符与结束符不正确,则提示错误信息。
运行结果如下:
七、思考题
1、如何将输入的两个字符(0--9)变为十进制或二进制数?
答:
将ASCII码变为十进制可以首先将两个字符均减去‘0’的ASCII码值,得到的偏移值便是该字符的一位十进制值,然后将第一个字符(十位数)的值用IMUL运算乘以10再加上第二个字符(个位数)的值即得到了十进制数。
若要将其化为二进制数,则可仍然首先将两个字符均减去‘0’的ASCII码值,得到的偏移值便是每个字符的一位十进制值,然后利用BCD码转化为二进制的方法得到二进制数。
也可以先将ASCII码值转化为十进制数,然后再将十进制数不断除2取余,便可得到相应的二进制数。
2、如何将选出的最小值(二进制或十进制)变为ASCII码再进行显示?
答:
可以将选出的最小值存放于MIN这一数据段的变量中,MIN+1存放十位数,MIN存放个位数,将十位与个位分别加上“0”的ASCII码,调用02号输出功能即可。
代码如下:
MOVAH,02H
MOVDL,MIN+1;显示最小值的十位
INT21H
MOVAH,02H
MOVDL,MIN;显示最小值的个位
INT21H
3、你觉得采用二进制运算还是十进制运算更适合于这个实验?
答:
由于本实验直接利用系统进行计算,因此使用的是二进制(十六进制)在机器中的运算,使用灵活、方便,代码简洁易懂。
八、实验总结、问题分析、心得体会
本次实验我充分利用了子程序的设计原理。
我将所有有关输出以及更改最小值等核心模块写入了子程序中,这样方便阅读,并且可以随时调用(虽然本程序并不需要在多处调用)。
通过实验,我充分体会到了子程序设计的重要性,在以后的不断实践中,我将多运用子程序设计的优势,将代码写得简洁易懂,并具有松耦合性。
这次实验中,我的另一个成果是实现了从输入的数据中得到最小值的算法:
将每次比较的最小值存入MINIMUM这一变量,使得MINIMUM+1、MINIMUM不断更新,分别对应着所有数据中的最小值的十位与个位。
另外,我也实现了分隔符与结束符的确定。
通过与相应符号的ASCII码值进行比较,可以得到是否满足该要求,若满足则执行相应步骤。
如结束符对应着退出循环并显示结果。
实验四子程序设计
一、实验目的
1、进一步掌握子程序设计方法;
2、进一步掌握基本的DOS功能调用。
二、实验内容
1、从键盘上输入某班学生的某科目成绩.输入按学生的学号由小到大的顺序输入。
2、统计检查每个学生的名次。
3、将统计结果在屏幕上显示。
4、为便于观察,输入学生数目不宜太多,以不超过一屏为宜。
输出应便于阅读.尽可能考虑美观。
5、输入要有检错手段。
三、程序流程图与程序模块图
四、实验原理
1、判断输入正误:
将输入与0、9的ASCII码值进行比较,若小于0或大于9则输入有误。
2、保证输入为两位数:
首先将十位与个位数的存储空间分别用两个变量表示,第一次输入的数存入十位存储空间里,第二次输入的数存入个位的存储空间里,同时使计数总值加一,记录输入数据个数。
若输入分数为一位数,则需要在十位上输入0。
在输入完两位数后,系统自动输出回车(转至行首)与换行(转至下一行相应位置),以示该数输入完毕。
在此设置,系统默认输入顺序按照学号顺序排列。
3、满分输入:
由于满分为三位数,因此需要单独设置一个标号以记录满分值,此处以输入“m”或“M”为满分的标志,同时在存储单元里存入“MA”这两个码值。
由于M的码值大于所有数字,因此对于排列顺序的正确性没有影响。
4、计算最低成绩及学号以及排名:
此算法利用了带进位的递增ASCII码,即将两位数的ASCII码视为BCD码,当个位数每次加一加至9时,十位数的ASCII码值加一,这样便获得了进位,使得输入数据的最大个数扩展为99个。
在计算最小成绩所在学号时,先将某位置的成绩与本轮循环的最小值进行比较,若比该值小,则将该位置的成绩更新入最小值存储单元中,同样将该位置以带进位的递增ASCII码为序号更新入学号的存储单元中,这样便可得到本轮最低成绩及其学号。
排名只需根据已经由大到小排好的顺序按带进位的递增ASCII码值进行输出即可。
5、排序算法:
基本思想是利用堆栈进行排序后数据的存储。
通过循环每次将成绩中的最小值以及其所在位置的ASCII码值(学号)筛选出来存入堆栈,再将此位置的成绩值置为0FFH,使得以后的循环不再考虑该值,继续选出最小值及其序号存入堆栈,这样便可将所有数据按从小到大的顺序筛选出来。
由于需要将比较过后的最小值位置处赋为0FFH,因此要根据学号寻找该学号的成绩,这就要进行ASCII码值与十进制的换算,把输入时按递增顺序存入的学号ASCII码值的十位乘以10再加上个位数。
代码如下:
MOVAL,0AH
MULDH
XORDH,DH;将高位清零
ADDAX,DX;AX=高位×10+低位
这样便可得到本次循环的最低成绩的位置,接着令其位置存储的成绩置为最大值0FFH,再进行下一轮循环,这样便可将所有数据按从小到大的顺序筛选出来。
6、输出列表:
利用堆栈里存入的成绩及学号的ASCII码值进行输出,由于堆栈里的成绩以及其学号都是按照从大到小的顺序排列的,所以每次只需取两个字(一个为成绩、一个为学号)进行输出,名次直接利用带进位的递增ASCII码的方法来进行输出即可。
五、实验源程序
DATASEGMENT;数据段设置了将要使用的变量
SIG0DB0;存放最小成绩的学号以及排名位置的个位
SIG1DB0;存放最小成绩的学号以及排名位置的十位
NUMBERDB0;存放数据个数
BUBBLEDB0;存放循环排序次数
HIGHPOSDB100DUP(0FFH);存放最小成绩的十位
LOWPOSDB100DUP(0FFH);存放最小成绩的个位
NUMEQU$-LOWPOS;存放循环最大次数
THREAD1DB0DH,0AH,'Inputthescoresofstudents:
',0DH,0AH,'$'