微机原理实验报告冒泡排序.docx
《微机原理实验报告冒泡排序.docx》由会员分享,可在线阅读,更多相关《微机原理实验报告冒泡排序.docx(24页珍藏版)》请在冰豆网上搜索。
微机原理实验报告冒泡排序
一、实验目的
(1)学习汇编语言循环结构语句的特点,重点掌握冒泡排序的方法。
(2)理解并掌握各种指令的功能,编写完整的汇编源程序。
(3)进一步熟悉DEBUG的调试命令,运用DEBUG进行调试汇编语言程序。
二、实验内容及要求
(1)实验内容:
从键盘输入五个有符号数,用冒泡排序法将其按从小到大的顺序排序。
(2)实验要求:
①编制程序,对这组数进行排序并输出原数据及排序后的数据;
②利用DEBUG调试工具,用D0命令,查看排序前后内存数据的变化;
③去掉最大值和最小值,求出其余值的平均值,输出最大值、最小值和平均值;
④用压栈PUSH和出栈POP指令,将平均值按位逐个输出;
⑤将平均值转化为二进制串,并将这组二进制串输出;
⑥所有数据输出前要用字符串的输出指令进行输出提示,所有数据结果能清晰显示。
三、程序流程图
开始
(1)主程序:
MAIN
初始化
键盘输入数据
调用INPUT子程序
显示输入错误
否
输入是否正确
是
显示原始数据
调用OUTPUT子程序
显示冒泡排序后的数据
调用SORT子程序
调用OUTPUT子程序
显示最小值Min
显示One子程序
显示最大值Max
调用One子程序
显示其余数平均值Average
调用One子程序
显示平均值二进制串Binary
调用One子程序
结束
(2)冒泡排序子程序:
SORT
COUNT1----外循环次数
进入
COUNT2----内循环次数
i----数组下标
初始化
COUNT1=N-1
COUNT2=COUNT1
SI=0
否
Ai≥iA+1
是
Ai与Ai+1两数交换
SI=SI+2
COUNT2=COUNT2-1
否
COUNT2=0?
是
COUNT1=COUNT1-1
否
COUNT2=0?
是
返回
四、程序清单
NAMEBUBBLE_SORT
DATASEGMENT
ARRAYDW5DUP(?
);输入数据的存储单元
COUNTDW5
TWODW2
FLAG1DW0;判断符号标志
FLAG2DB0;判断首位是否为零的标志
FAULTDW-1;判断出错标志
CRDB0DH,0AH,'$'
STR1DB'PleaseinputfivenumbersseperatedwithspaceandfinishedwithEnter:
','$'
STR2DB'Theoriginalnumbers:
','$'
STR3DB'Thesortednumbers:
','$'
STR4DB'TheMin:
','$'
STR5DB'TheMax:
','$'
STR6DB'TheAverage:
','$'
STR7DB'Thebinarysystemoftheaverage:
','$'
STR8DB'Inputerror!
Pleaseinputagain!
''$'
DATAENDS
CODESEGMENT
MAINPROCFAR
ASSUMECS:
CODE,DS:
DATA,ES:
DATA
START:
PUSHDS
ANDAX,0
PUSHAX
MOVAX,DATA
MOVDS,AX
LEADX,STR1
MOVAH,09H;9号DOS功能调用,提示输入数据
INT21H
CALLCRLF;回车换行
REIN:
CALLINPUT;调用INPUT子程序,输入原始数据
CMPAX,FAULT;判断是否出错,
JEREIN;出错则重新输入
LEADX,STR2
MOVAH,09H;9号DOS功能调用,提示输出原始数据
INT21H
CALLOUTPUT;调用OUTPUT子程序,输出原始数据
CALLSORT;调用SORT子程序,进行冒泡排序
LEADX,STR3
MOVAH,09H;9号DOS功能调用,提示输出排序后的数据
INT21H
CALLOUTPUT;调用OUTPUT子程序,输出排序后的数据
ANDSI,0
ANDBX,0
MOVBX,ARRAY[SI];将最小值存入BX
LEADX,STR4
MOVAH,09H;9号DOS功能调用,提示输出数据的最小值
INT21H
CALLONE;调用ONE子程序,输出最小值
CALLCRLF
LEADX,STR5
MOVAH,09H;9号DOS功能调用,提示输出排序后的最大值
INT21H
MOVBX,ARRAY[SI+8]将;最大值存入BX
CALLONE;调用ONE子程序,输出最大值
CALLCRLF
LEADX,STR6
MOVAH,09H;9号DOS功能调用,提示输出平均值
INT21H
ANDDX,0
MOVAX,ARRAY[SI+2];将去掉最大最小值的其余各数之和存入AX
ADDAX,ARRAY[SI+4]
ADCAX,ARRAY[SI+6]
MOVCX,COUNT;计数器CX=5
DECCX;CX←CX-1
DECCX
DIVCX;字除法,余数存入AX
MOVBX,AX;将余下各数的平均值存入BX
CALLONE;调用ONE子程序,输出去掉最大最小值的其余数平均值
CALLCRLF
LEADX,STR6
MOVAH,09H;9号DOS功能调用,提示输出平均值的二进制串
MOVCX,16;16位二进制串,计数器初始值为16
LL1:
ANDDX,0
DIVTWO
PUSHDX
LOOPLL1
MOVCX,16
LL2:
POPDX
ADDDL,30H;将DL中的数进行ASCII码转换
MOVAH,2;2号DOS功能调用,输出字符“0”或“1”
INT21H
LOOPLL2
MOVAH,4CH
INT21H;4C号功能调用,返回DOS
MAINENDP
;--------------------------------------------------------------------------------------------------------------------------------
子程序:
CRLF
功能:
回车和换行
;--------------------------------------------------------------------------------------------------------------------------------
CRLFPROC
LEADX,CR
MOVAH,09H
INT21H
RET
CRLFENDP
;--------------------------------------------------------------------------------------------------------------------------------
子程序:
INPUT
功能:
输入一组数据
;--------------------------------------------------------------------------------------------------------------------------------
INPUTPROC
MOVCX,COUNT;计数器CX=5
ANDSI,0
NEXT1:
CALLDTB;调用DTB子程序,将输入转换为二进制数
DECCX;CX←CX-1
CMPDL,20H;判断输入字符是否为空格符
JESTO
CMPDL,0DH;判断输入字符是否为换行符
JEEXIT2
CALLCRLF
ERROR:
LEADX,STR8
MOVAH,09H;9号DOS功能调用,提示输入不合法
INT21H
CALLCRLF
MOVAX,FAULT;以AX中的值作为出错标志
JMPEXIT3
STO:
MOVARRAY[SI],BX;是空格符,将BX中的二进制数存入存储单元
ADDSI,2
JMPNEXT1
EXIT2:
MOVARRAY[SI],BX;是换行符,将BX中的二进制数存入存储单元
CALLCRLF
EXIT3:
RET
INPUTENDP
;--------------------------------------------------------------------------------------------------------------------------------
子程序:
DTB
功能:
将键盘输入的十进制数转换为二进制数形式存入BX
;--------------------------------------------------------------------------------------------------------------------------------
DTBPROC
ANDBX,0
ANDFLAG1,0;符号标志,0为正,1为负
CHAR:
MOVAH,01H;1号DOS功能调用,输入一个字符,存入AL
INT21H
MOVDL,AL
CMPAL,2DH;判断输入字符是否为负号"-"
JNZNEXT2
MOVFLAG1,1;是负数,将符号标志FLAG1置1
JMPCHAR
NEXT2:
SUBAL,30H;判断输入字符是否在0-9之间
JLNEXT3
CMPAL,09H
JGNEXT3
CBW
XCHGAX,BX;输入字符在0-9之间,将BX中的数乘以10
MOVCX,10
MULCX
XCHGAX,BX
ADDBX,AX;将BX中的数与新输入的数相加
JMPCHAR
NEXT3:
CMPFLAG1,1;根据符号标志判断输入是否为负
JNZEXIT1
NEGBX;对BX中的数求补
EXIT1:
RET
DTBENDP
;--------------------------------------------------------------------------------------------------------------------------------
子程序:
OUTPUT
功能:
输出一组数据
;--------------------------------------------------------------------------------------------------------------------------------
OUTPUTPROC
CALLCRLF
MOVDI,COUNT;计数器DI=5
ANDSI,0
GO1:
MOVBX,ARRAY[SI];将存储单元的第一组数据存入BX
TESTBX,8000H;判断正负
JZGO2
MOVDL,2DH
MOVAH,02H;2号DOS功能调用,输出负号"-"
INT21H
NEGBX
GO2:
CALLONE;调用ONE子程序,将BX中二进制数转换为十进制数输出
MOVDL,20H
MOVAH,02H;2号DOS功能调用,输出空格符
INT21H
ADDSI,2;指针指向下一数据
DECDI;DI←DI-1
JNZGO1;计数器DI不为零,继续循环
CALLCRLF
RET
OUTPUTENDP
;--------------------------------------------------------------------------------------------------------------------------------
子程序:
ONE
功能:
将BX中的的二进制数转换为十进制数,由高到低各位依次输出
;--------------------------------------------------------------------------------------------------------------------------------
ONEPROC
PUSHBX
PUSHCX
PUSHSI
PUSHDI
MOVCX,10000;除数存入CX
CALLBTD
MOVCX,1000
CALLBTD
MOVCX,100
CALLBTD
MOVCX,10
CALLBTD
MOVCX,1
CALLBTD
ADDDL,FLAG2
CMPDL,30H;与"0"的ASCII码比较,判断该数是否为"0"
JNEQUIT3
MOVAH,02H;2号DOS功能调用,输出"0"
INT21H
QUIT3:
POPDI
POPSI
POPCX
POPBX
ANDFLAG2,0;将首位标志FLAG2重新置0
RET
ONEENDP
;--------------------------------------------------------------------------------------------------------------------------------
子程序:
BTD
功能:
将BX中的二进制数转换为一个十进制数输出
;--------------------------------------------------------------------------------------------------------------------------------
BTDPROC
MOVAX,BX
ANDDX,0
DIVCX;字除法,商值存入AX,余数存入DX
MOVBX,DX;余数存入BX
MOVDL,AL
ADDDL,30H;对DL中的数进行ASCII码转换
CMPFLAG2,0;判断是否为首位数据
JNEQUIT1
CMPDL,30H;是首位则判断是否为"0"
JEQUIT2;是"0"则不输出
MOVFLAG2,1;不是"0"将首位标志置1
QUIT1:
MOVAH,02H;2号DOS功能调用,输出一位十进制数
INT21H
QUIT2:
RET
BTDENDP
;--------------------------------------------------------------------------------------------------------------------------------
子程序:
SORT
功能:
冒泡排序
;--------------------------------------------------------------------------------------------------------------------------------
SORTPROC
CLD
MOVCX,COUNT;初始化计数器CX
DECCX;CX=4
LOO1:
MOVDI,CX;CX中的数存入DI
ANDSI,0
LOO2:
MOVAX,ARRAY[SI]
CMPAX,ARRAY[SI+2];相邻两数进行比较
JLLOO3
XCHGAX,ARRAY[SI+2];前一数较大则进行数据交换
MOVARRAY[SI],AX
LOO3:
ADDSI,2;前一数较小,则进行下一组比较
LOOPLOO2;CX=0,停止内循环
MOVCX,DI;还原计数器CX的值
LOOPLOO1;CX=0,停止外循环
RET
SORTENDP
;--------------------------------------------------------------------------------------------------------------------------------
CODEENDS
ENDSTART
五、运行结果
(1)对300,250,280,240,260五个数进行冒泡排序,运行结果如下:
(2)对-1,2,54,-38,43五个数进行冒泡排序,运行结果如下
(1)当输入不合法时,出现错误提示:
(4)当输入数据不足5个时程序自动补0:
六、心得体会
在本次汇编语言程序设计实验中,我们学习了汇编语言的循环结构,并对冒泡排序法进行了
汇编程序设计,我首先编写了对给定数据进行冒泡排序的算法设计,这有助于我熟悉冒泡排
序的逻辑结构,理清设计思路。
汇编语言与C语言相似,然而,在设计过程中,我才意识到,
要用汇编语言写出完整的算法程序并不是一件简单的事,一个微小的错误就可能导致整个程
序无法正常运行。
在编程时,出现了各种各样的错误,如写程序时没有切换成英式标点,16
进制数未加“H”符号,做字除法运算时忘记将DX清零而导致“DivideOverflow”。
这些错
误都在汇编调试过程中得到改正。
在接下来的上机课程中,我们按照老师的要求对改程序进行了进一步设计——对从键盘输入
的数据进行冒泡排序。
这个算法程序较为复杂,为了使程序能够更加简洁明了,我对其进行
了模块化设计,将输入、输出、冒泡排序等功能分离出来,用子程序一一实现。
由于键盘输
入的数据并不能简单的从位数来判定输入输出,我设定将Space作为分隔符,而结束输入时
按Enter键。
为了防止无用输入和输出数据时遗漏“0”,引入了首位符号标志来进行判定。
对算法进行模块化设计使得实现各功能时无需多重循环,原数据和排序后数据的输出都可由
OUTPUT子程序实现,而最大值、最小值和平均值等都可以由ONE子程序实现单个数据的输
出,极大的减少了算法的重复。
在这一阶段,我也遇到了一些困难难,例如在输入完数据回
车后程序显示输入错误,经过排查才发现在一2号DOS功能调用时,只写了功能号而忘记
“INT21H”,导致数据无法正常显示。
还有诸如子程序结束时没加返回指令RET,命名过程
名时与关键字重复,更改过程名后忘记修改跳转指令等等。
在发现错误和改正错误的过程中
增强了我对汇编语言的掌握程度,对算法设计有了更深的了解。
接下来,我还对该算法程序进行了进一步优化,包括数据对齐,出错提示和进行有符号数的
排序。
为了实现数据对齐,我增加了CRLF子程序,方便实现回车换行功能。
而为了在输入
不合法时,进行错误提示,我定义了出错标志。
该算法可以对-32768---32767之间的整数进
行冒泡排序,为了实现这一功能,我使用了符号标志进行判定,1为负数,0为正数。
在上机实验过程中,我对各条语句的含义都有了更深的理解,编写程序和独立解决问题的能
力都得到了加强。
与此同时,我也认识到自己还有诸多不足,例如程序设计不够简洁,修改
算法时往往不能前后兼顾,编写程序不够审慎等等,这些都是我在今后的日子里需要进一步
学习和掌握的。