下面从整体结构特点、程序设计、技巧及可改进处等方面来进一步分析本参考程序。
1.双重循环程序的结构特点
1)内循环程序的初始化在外循环体中。即进入内循环体前由外循环进行初始化。其具体语句是:“MOV R0,#30H”对数组指针R0赋初值;“MOV R2,#32”与“DEC R2”是对内循环计数器R2设置初值,如图4-16所示。
2)内循环体必须套在外循环内,不能交叉。即程序运行时先进入外循环,后进入内循环体,在内循环计数到预定次数后,才能回到外循环体,如图4-20所示。
本程序具体情况为:外循环体入口地址标号BUBBLE在前,内循环体入口地址标号BULOOP在后;内循环体计数控制语句“BUNEXT:DJNZ R2,BULOOP”在前,其转移目标地址只能是内循环体入口地址;外循环体控制语句“JB 7FH,BUNEXT”在后,其转移目标地址只能是外循环体入口地址,如图4-14、图4-20所示。
3)外循环程序的初始化也可以在外循环体中进行,这是本程序的一个很有趣的做法。其具体语句是语句(4)“CLR 7FH”,只有每次在进入外循环体后,用此语句对7FH标志位清零,才能保证外循环体的控制语句(18)“JB 7FH,BUNEX”正常工作,否则本程序就永远停止不下来。
2.几点有用的设计技巧
要设计出一个好的程序,不仅要构思出正确的设计方案与流程图,还需要注意运用具体指令的技巧。如何提高设计技巧呢?最好的方法是在实践中分析、积累。本参考程序中,注意以下几个重要语句的设计技巧:
(1)CJNE与JC指令搭档使用技巧 本程序中采用CJNE与JC指令搭档的方式来比较两个数的大小及分支,见语句(10)、(11)组成的程序段2。其主要使用技巧是将CJNE指令的转移目标定为下一条指令JC,这样无论CJNE比较转移指令的结果如何,程序都接着执行第2条JC指令,按Cy值正式进行分支。
这一做法的好处是:
1)利用CJNE指令比较两个数大小时,能影响Cy位而不影响A中内容。
2)弥补CJNE指令不能按Cy进行分支的不足。
因而可以说这两条指令合起来使用时,就等于是一条比较两个数后按Cy位转移的指令。
具体来说,语句(10)“CJNE A,21H,LOOP”在这里的作用主要是通过比较A和21H中的内容来影响Cy标志位,然后转入语句(11)“LOOP JC BUNEXT”,进一步按Cy位状态进行分支:
当A=(21H)时,Cy=0,程序继续按顺序执行,进入语句(12),交换两数的位置。
当A>(21H)时,Cy=0,程序继续按顺序执行,进入语句(12),交换两数的位置。
当A<(21H)时,Cy=1,程序跳转到标号地址BUNEXT处,不用交换数。
(2)交换两数位置的技巧 冒泡排序程序中的另一个关键技术是当大数在低字节时,需要与上一位交换位置,也就是“冒泡”。(www.xing528.com)
本程序采用数据指针法来交换两个数在数组中的位置,其过程分为四步:见参考程序的语句(12)、(13)、(14)、(15)。
第一步,语句(12)“MOV@R0,20H”,将放在低字节的大数送入数组的高字节,因为此时数据指针仍指向数组的高字节单元。
第二步,语句(13)“DEC R0”,使数据指针调低一单元,为下一步换低字节的数作准备。
第三步,语句(14)“MOV@R0,21H”,将原来在高字节的数送入低字节单元,完成数据交换。
第四步,语句(15)“INC R0”,用以恢复数据指针值,以便进行下一个数的比较过程。
上述过程的关键是在用数据指针R0灵活改变CPU访问内存单元的地址时,必须记住@R0在每一步前的实际指向。如,在第一步语句(12)前,CPU是先取低位数后取高位数来进行比较的,比较后当(20H)>(21H)需要交换数的位置时,@R0仍指向数组的高位置单元。所以语句“MOV@R0,20H”就能正确地将大数放入高字节单元,这一点技巧请读者要好好领会。
(3)标志位单元的应用技巧 本程序中以7FH位单元作为控制外循环走向的标志位,是一个很好的做法。这一构思来自于对冒泡排序过程的深入理解,因为当7FH为零时,表明在这一轮大循环中没有发生数交换,即数组已完成冒泡排序,也就可以停止执行程序了。
显然,这一标志位控制方法要比通常先预设外循环次数的做法合理些,也是值得学习的设计技巧。
3.讨论
任何程序都有可改进之处,本参考程序的可讨论改进处有:
1)如何提高程序的冒泡排序速度?本程序的每轮内循环次数都被设定为固定数n-1次,但实际上每轮内循环后“冒泡”的高位置数增加1个,余下需要重新循环比较的数就减少1个,则下一轮内循环的次数也可减少1次,这样就需将每轮内循环次数改为变数,如
可见,在程序中增加R3,用作内循环次数的初始值变量,就可以每轮内循环次数逐一减少,达到提高冒泡排序速度的目的。
2)在两个数相等时,还有必要交换位置吗?显然,没有必要。但本程序语句(11)“LOOP:JC BUNEXT”将(20H)=(21H)与(20H)<(21H)两种情况分支为一类,都进行交换数处理,这虽然没有错,但也不太合理。改进的措施将(20H)=(21H)与(20H)>(21H)两种情况分为一类,不进行数交换。如:
改用JNC指令可将(20H)=(21H)与(20H)>(21H)分为一类,不再进行数交换,但要在其后增加一条语句“SJMP BUNEXT”。读者也可试试其他改进方法,看能否更合理些。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。