微机原理软件实验报告.docx
《微机原理软件实验报告.docx》由会员分享,可在线阅读,更多相关《微机原理软件实验报告.docx(51页珍藏版)》请在冰豆网上搜索。
微机原理软件实验报告
信息与通信工程学院
微机原理软件实验报告
班级:
姓名:
学号:
日期:
2011年12月
实验一DEBUG的使用
一、实验目的
1.掌握汇编程序的编辑、编译、连接和执行的全过程;
2.学习和掌握用DEBUG调试程序的方法。
二、实验内容
1.用编辑软件,输入以下汇编语言源程序:
DATSEGMENT
ADB20
BDB15
YDB3DUP(0)
ZDB0,0
DATENDS
STASEGMENTSTACK
DW50DUP(?
)
STAENDS
CODSEGMENT
ASSUMECS:
COD,DS:
DAT
STARPROCFAR
PUSHDS
XORAX,AX
PUSHAX
MOVAX,DAT
MOVDS,AX
MOVAX,STA
MOVSS,AX
MOVAL,A
MOVZ,AL
MOVZ+1,AL
CALLSUB1
MOVAL,B
MOVZ,AL
MOVZ+1,AL
CALLSUB1
MOVAL,A
MOVZ,AL
MOVAL,B
MOVZ+1,AL
CALLSUB1
ADDWORDPTRY,AX
ADCBYTEPTR[Y+2],0
RET
STARENDP
SUB1PROC
MOVAL,Z
MOVAH,Z+1
MULAH
ADDWORDPTRY,AX
ADCBYTEPTR[Y+2],0
RET
SUB1ENDP
CODENDS
ENDSTAR
2.通过编译,连接形成可执行文件。
3.用DEBUG将可执行文件调入,并进行调试。
1)用D命令观察数据区在内存中的具体内容,记录单元A和B的具体地址。
2)用U命令对目标代码反汇编,观察反汇编后的结果。
注意发现源程序的起始位置,并记录这个起始地址。
3)用T命令作单步跟踪调试。
比较每条指令执行后的结果和原来的理解是否一致,得出程序运行的结果:
它们是写在什么单元,具体内容是什么;并判断结果是否正确。
在子程序SUB1的入口处设一断点,用G命令执行程序。
在断点处观察堆栈的内容,比较堆栈的内容和程序返回地址是否一致。
4)用E命令修改单元A,B的内容,重新执行程序,并记录结果。
5)用M命令和A命令对程序进行修改:
将主程序中最后两条指令(ADD和ADC)修改为一条CALLSUB1指令,重新执行程序。
6)退出DEBUG。
4.重新使用编辑软件,把源程序最后一句中的STAR去掉。
再次生成可执行文件,并用DEBUG调入内存。
当使用U命令时,显示的结果与前一次(未加STAR)的结果有何不同?
三、预习思考
1.熟悉常用的DEBUG命令。
答:
常用的DEBUG命令如下图表所示。
2.阅读并分析程序的功能。
答:
程序完成的功能是计算两个数的完全平方和,即计算a2+b2+ab
3.若SS=2000H,SP=FFFFH,向堆栈中压入4字节数据后,如何用D命令显示压入堆栈的内?
答:
使用的命令是:
D2000:
FFFB,即使用段基址加偏移量查看。
四、实验过程
以下由实验截图展现具体的实验过程,截图进行了详细标注,便于阅读。
编译
上图为编译、链接形成可执行文件的过程。
(1)下图展现了进行反编译然后使用D命令查看数据段中A、B值的过程。
AB段地址:
142EHA:
偏移地址0000H物理地址142E0H,
B:
偏移地址0001H物理地址142E1H
(2)下图为用u命令进行反汇编的结果,CS段地址1436H,起始偏移地址0000H
(3)下图是用T命令作单步跟踪调试,并在SUB1出设置一断点,可以看到程序执行到CALL0003F时跳到了子程序进行执行,并将断点地址压入堆栈中,各寄存器的值均有显示。
CALLSUB1语句地址
CALL语句的下一个语句的地址
(4)下图使用E命令对数据段数据A和B进行了修改,分别由20和15改为了4和8,修改后重新运行用D命令进行了查看。
修改之后
修改之前
修改之后运行结果
(6)用M命令和A命令对程序进行修改:
将主程序中最后两条指令(ADD和
ADC)修改为一条CALLSUB1指令,重新执行程序.下图是原程序
下图将sub1的代码转移到0055h的位置,防止修改后两句命令时影响sub1子程序
下图是用A命令修改call子程序的命令及后两句命令
下图为重新运行结果,与预测结果相符
(6)重新使用编辑软件,把源程序最后一句中的STAR去掉。
再次生成可执行文件,再次DEBUG时。
当使用U命令时,结果如下图所示。
可以看到,没有ENDSTAR语句,编译器将不知道代码段的入口地址是多少,导致从数据段开始译码,后续译码全部紊乱。
ENDSTAR的作用是指示编译器程序结束,同时告诉编译器程序执行时代码段的入口地址。
(7)下图为退出debug的结果
五、实验总结
此次实验是微机原理软件实验的第一次实验。
由于平时只是注重理论的学习,没有多少实际编程和调试经验,上机操作还不熟练。
以后需要加强实践。
这次实验我学会了汇编程序的基本调试方法,也体会到汇编的调试和C/C++或者Java调试的差异。
汇编的调试需要深入堆栈和内存区,关心每一寄存器和每一个指令。
这也体现汇编是底层语言的特点。
在这次实验中,我学会了各种调试命令,这对以后编程有着重要的意义,对于程序中的逻辑错误知道怎么去找问题。
实验二分支、循环程序设计
一、实验目的
1.开始独立进行汇编语言程序设计;
2.掌握基本分支,循环程序设计;
3.掌握最简单的DOS功能调用。
二、实验内容
1.安排一个数据区,内存有若干个正数,负数和零。
每类数的个数都不超过9。
2.编写一个程序统计数据区中正数,负数和零的个数。
3.将统计结果在屏幕上显示。
4.(扩展题)统计出正奇数、正偶数,负奇数、负偶数以及零的个数。
三、预习思考
1.十进制数0~9所对应的ASCII码是什么?
如何将十进制数0~9在屏幕上显示出来?
答:
0~9分别对应ASCII码的30H~39H。
欲将十进制数0~9显示在屏幕上,只需要用二进制数0~9分别加上30H即可。
2.如何检验一个数为正,为负或为零?
你能举出多少种不同的方法?
答:
方法有多种,只要能通过指令影响标志寄存器,就可以通过标志寄存器来判断出正负和零,现举出两种。
一是直接用CMP命令和0比较,然后用JZ等命令进行判断;二是和0相比是否相等,然后用该数(假设为8位)和10000000相与,取出符号位判断,可区分正负。
四、实验过程
(一)、流程图
(二)、源代码
;1.安排一个数据区,内存有若干个正数,负数和零.每类数的个数都不超过9.
;2.编写一个程序统计数据区中正数,负数和零的个数.
;3.将统计结果在屏幕上显示.
DATASEGMENT
NUMDB-3,0,5,6,4,-6;要比较的数据
COUNTEQU$-NUM;存放数据的长度
NUM_ADB0;存放大于0的个数
NUM_EDB0;存放等于0的个数
NUM_BDB0;存放小于0的个数
STRINGDB0DH,0AH,'$'
STRING1DB'NEGATIVE',3AH,20H,'$'
STRING2DB'EQUAL',3AH,20H,'$'
STRING3DB'POSITIVE',3AH,20H,'$'
DATAENDS
STACKSEGMENTSTACK'STACK'
DB100DUP(?
)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
STARTPROC
MOVAX,DATA
MOVDS,AX
MOVCX,COUNT
MOVDX,0
MOVAX,0
MOVBX,OFFSETNUM
LOOP1:
ANDBYTEPTR[BX],0FFH
JZEA_IN
JNSA_IN
INCAL
JMPNEXT
EA_IN:
INCDL
JMPNEXT
A_IN:
INCDH
NEXT:
INCBX
LOOPLOOP1
MOVNUM_B,AL
MOVNUM_E,DL
MOVNUM_A,DH
MOVAH,09H
MOVDX,OFFSETSTRING1
INT21H
MOVAH,02H
MOVDL,NUM_B
ADDDL,30H
INT21H;
MOVAH,09H
MOVDX,OFFSETSTRING
INT21H
MOVAH,09H
MOVDX,OFFSETSTRING2
INT21H
MOVAH,02H
MOVDL,NUM_E
ADDDL,30H
INT21H;
MOVAH,09H
MOVDX,OFFSETSTRING
INT21H
MOVAH,09H
MOVDX,OFFSETSTRING3
INT21H
MOVAH,02H
MOVDL,NUM_A
ADDDL,30H
INT21H
MOVAH,09H
MOVDX,OFFSETSTRING
INT21H
MOVAX,4C00H
INT21H
STARTENDP
CODEENDS
ENDSTART
(三)、实验分析
数据区待统计的数据为:
-3,0,5,6,4,-6
实验结果如下图所示。
本实验较为简单,意在练习基本的分支、循环结构。
关键的点在于和0FFH相与,区分正负和零。
使得程序更加流畅和简洁,思路也更清晰。
五、实验总结
实验中设计好的计算思路是很重要的,汇编的代码由各种跳转和逻辑结构组成,需要考虑代码间的逻辑关系,否则容易出错。
语法错误是很显而易见的,但逻辑错误却不容易发现。
当有大量判断和循环存在时,需要考虑清楚程序跳转的条件和方向,这点和高级语言有较大差异,汇编本质上没有循环和分支,都是通过将IP赋予代码区地址进行跳转实现的,程序员需要自主控制如何跳转,向何处跳转,这点和C/C++中饱受诟病的goto语句处理有些类似。
考虑到实验练习的重点在分支循环结构,此次写代码时暂时没有使用子程序或宏,导致输出部分代码有些过长。
实验三代码转换程序设计
一、实验目的
1.掌握几种最基本的代码转换方法;
2.运用子程序进行程序设计。
二、实验内容
1.从键盘上输入若干两位十进制数,寻找其中的最小值,然后在屏幕上显示出来。
2.两个十进制数之间的分隔符,输入结束标志自定,但要在报告中说明。
3.对输入要有检错措施,以防止非法字符输入,并有适当的提示。
4.将整个程序分解为若干模块,分别用子程序实现。
在报告中要给出模块层次图。
三、预习思考
1.如何将输入的两个字符(0~9)变为十进制或二进制数?
答:
输入的字符0~9是ASCII码表示的,对应于30H~39H,通过减去30H,可以转换为相应的计算机数。
2.如何将选出的最小值(二进制或十进制)变为ASCII码再进行显示?
答:
如果采用输入时把ASCII码转换为数字,然后比较数字的大小再输出,那么输出时还需要把数字再次转换为ASCII码。
这是不明智的。
可以直接读入并存储数字的ASCII码,容易比较其大小,然后直接输出ASCII码即可。
3.你觉得采用二进制运算还是十进制运算更适合于这个实验?
答:
采用二进制或者十进制都需要进行ASCII码到数字的转换和其反向转换,换用新的思路可以大大简化编程负担。
即直接使用数字对应的ASCII比较,分别比较十位和个位,最后直接输出字符即可。
四、实验过程
(一)流程图
(二)模块层次图
(三)源代码
DATASEGMENT
NUMDB31
DB0
DB31DUP(?
)
MINTDB?
MINGDB?
;NUMCDB0,1,2,3,4,5,6,7,8,9
OKFDB0
ERRSDB'ERRORTYPE',0DH,0AH,'$'
TIPDB'TYPEININTEGER,SPACETOSEPRATE',0DH,0AH,'$'
OUTPUTDB'THEMINIS','$'
HHDB0AH,'$'
DATAENDS
;10
STACKSEGMENTSTACK'STACK'
DB100DUP(?
)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
STARTPROC
MOVAX,DATA
MOVDS,AX
MOVES,AX;20
MOVOKF,1
AG:
LEADX,TIP;用户输入提示
MOVAH,09H
INT21H
LEADX,NUM;输入字符
MOVAH,0AH
INT21H
LEADX,HH;换行
MOVAH,09H;30
INT21H
LEABX,NUM;确定输入数的个数,保存到CX中
INCBX
MOVAL,[BX]
MOVAH,0
MOVCL,3
DIVCL
MOVCL,AL
MOVCH,0;40
INCBX
CALLCHECK
CMPOKF,0
JZAG
MOVAL,[BX]
MOVMINT,AL;将第一个数存入最小值中
MOVAL,[BX+1]
MOVMING,AL
ADDBX,3;将第二个数的偏移地址存入BX中
CALLLF;调用查找最小值函数
LEADX,OUTPUT
MOVAH,09H
INT21H
MOVAH,02H
MOVDL,MINT
INT21H
MOVDL,MING
INT21H
EXIT:
MOVAX,4C00H
INT21H
STARTENDP
;检查是否输入出错
;是数字+数字+空格则判断正确,其余情况判断错误
CHECKPROC
PUSHBX
PUSHCX
CNUM:
PUSHCX
MOVCX,2
CFS:
MOVAL,[BX]
CMPAL,30H
JBERR
CMPAL,39H
JBENPL
ERR:
MOVOKF,0
MOVAH,09H
MOVDX,OFFSETERRS
INT21H
POPCX
JMPRE
NPL:
INCBX
LOOPCFS
CSP:
MOVAL,[BX]
CMPAL,20H
JNZERR
NEXT:
INCBX
POPCX
LOOPCNUM
MOVOKF,1
RE:
POPCX
POPBX
RET
CHECKENDP
;查找最小值
;入口参数BX,出口参数MINT,MING
LFPROC
PUSHCX
DECCX
LFC:
MOVAL,[BX]
CMPAL,MINT
JBEXCH;十位数比最小数的十位数小,交换
JANLF;十位数比最小数的十位数大,进入下一个数的比较
MOVAL,[BX+1];十位数与最小数的十位数相等,比较个位数
CMPAL,MING
JAENLF
EXCH:
MOVAL,[BX]
MOVMINT,AL
MOVAL,[BX+1]
MOVMING,AL
NLF:
ADDBX,3
LOOPLFC
POPCX
RET
LFENDP
CODEENDS
ENDSTART
(四)实验分析
下图是实验输出结果截图。
实验中以空格为分隔符,空格的个数不限制,以回车为输入结束标志符。
对输入的数字进行了位数和范围的严格限制,即必须是两位数字,如果数字小于10,需要补齐零。
实验中对输入错误执行严格的检查,出错则重新输入。
判断输入错误的核心思路为:
以空格为分割,以回车结束,要求必须是两位数,也即,一位数字后不能有空格,两位数字后必须有空格,以上三种情况囊括了所有可能的格式错误,不满足任何一个条件即出错。
满足格式输入后,再判断字符的是否0~9,不是则出错。
每项错误均已错误列表的形式给出,打印出错误提示。
总结实验中的关键设计思路如下:
1、严格的输入格式检查,严格的输入字符有效性检查。
2、以数组方式进行存储,每两个BYTE存储一个输入的两位数,存储格式为字符ASCII码。
不进行字符ASCII码到数字的转换。
3、比较数字大小时,采用分别比较高位ASCII码和低位ASCII码的方式,从而不用在输入时将字符存储为数字,输出时也不用再进行逆转换。
程序效率大为提高。
4、为使得程序结构清晰,减小代码耦合度,采用了多子程序的设计方式。
把实验任务分为三步:
读取输入、找出最小、输出打印,分别以子程序方式实现,主调函数依次调用完成实验任务。
五、实验总结
实验中比较大小的方式有多种,如何采用更加简洁有效的方式是值得思考的问题。
考虑到ASCII也是可以比较的,且十位数和个位数是可以分别比较的这一情况,我采用了巧妙的方式进行处理。
这说明,在实际的编程中,需要根据具体情况调整一般方法,使得方法更加简洁可行且有效。
实验四子程序设计
一、实验目的
1.进一步掌握子程序设计方法;
2.进一步掌握基本的DOS功能调用。
二、实验内容
1.从键盘上输入某班学生的某科目成绩。
输入按学生的学号由小到大的顺序输入。
2.统计检查每个学生的名次。
3.将统计结果在屏幕上显示。
4.为便于观察,输入学生数目不宜太多,以不超过一屏为宜。
输出应便于阅读.尽可能考虑美观。
5.输入要有检错手段。
三、预习思考
1.如何确定一个学生在这门科目中的名次?
答:
有两种基本思路,一是抽取每个学生的成绩和其他所有学生的成绩进行比较,然后统计比其分数高的学生,得出该学生的名次;二是把学生成绩存入连续内存区域,即数组方式,取得每个学生的成绩偏移量,即成绩指针。
然后比较指针所指的成绩的大小,根据比较结果移动指针完成排序。
具体排序时可以采用诸多的方式,比如冒泡法,快速排序法等等,均是可行的。
本实验采用第二种方式,用冒泡法予以具体实现。
2.输入结束后,采用什么方法进行比较以得到学生的名次最为简单?
答:
如上问所述,采用冒泡排序法可获得较好的时间和空间性能。
冒泡法平均时间性能O(N2)。
相比于直接比较,性能有所改善。
但相对于快速排序、归并排序等优化的算法的时间复杂度O(N*log2N)还不够好。
但后两者使用汇编实现代码的复杂度和编程要求要高。
考虑到学生人数比较少,使用冒泡法是比较简洁的,时间性能是可以接受的。
3.准备好模块层次图。
答:
见下文“实验过程”中所示。
4.给出输出显示的形式。
答:
输出以列表形式给出。
学号、分数、名次各一列。
具体形式参见实验分析部分的输出截图。
四、实验过程
(一)流程图
(二)模块层次图
(三)源代码
DATASEGMENT
RSCOREDB40DUP(0);存储分数排名
SCOREDB100
DB0
DB100DUP(?
)
ASCOREDB40DUP(0);存储调整后的分数值
OKFDB0;输入数据有效位
;10
SCOUNTDB1
REFDB09H;十进制转BCD参考数
TENDB0
ERRSDB'ERRORTYPE',0DH,0AH,'$';出错提示符
TIPDB'TYPEININTEGER,SPACETOSEPRATE',0DH,0AH,'$';输入提示符
HHDB0DH,0AH,'$';换行字符串
STRNUMEQU$-HH
NODB'NO.','$';号数字符串
SPOUTDB3AH,'','$';冒号+空格字符串
STADB'STATIC',3AH,'$';显示统计数据
DATAENDS
;27
STACKSEGMENTSTACK'STACK'
DB100DUP(?
)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
;打印字符串的宏
PRINTMACROPARA
PUSHAX
PUSHDX
MOVAH,09H
MOVDX,OFFSETPARA
INT21H
POPDX
POPAX
ENDM
STARTPROC
MOVAX,DATA
MOVDS,AX
MOVES,AX
LEADI,ASCORE;ASCORE存放调整后的分数数组
LEASI,RSCORE;RSCORE存放排序后的分数数组
CLD
AG:
MOVOKF,1
MOVNUMC,1
MOVSCOUNT,1
MOVCL,7
MOVCH,0
LEABX,COUNT
CLE:
MOVBYTEPTR[BX],0
INCBX
LOOPCLE
PRINTTIP;提示用户输入
LEADX,SCORE;输入字符
MOVAH,0AH
INT21H
;60
PRINTHH;换行
;确定输入字符的个数,保存到CL中
LEABX,SCORE;BX指向SCORE首单元
INCBX;BX指向字符数单元
MOVCL,[BX];CL存字符数目
MOVCH,0
INCBX;BX指向第一个字符单元
CALLCHECK;判断是否输入出错
CMPOKF,0;如果出错重新输入
JZAG
;调整分数及排序
MOVCL,COUNT;CL存学生数目
MOVCH,0
LOOP1:
MOVAL,[BX]
SUBAL,30H
MOVAH,[BX+1];查找出这个数是一位数两个数还是三位数
CMPAH,20H
JZLOC1;一位数,跳转到LOC1
MOVAH,[BX+2]
CMPAH,20H
JZLOC2;两位数,跳转到LOC