打印

用汇编做了一个排序,不太满意,怎样修改?

[复制链接]
1648|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
天雨粟|  楼主 | 2008-10-7 19:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用汇编做了一个排序,不太满意,怎样修改?

内存中有一系列数,首地址存在R3中,长度在R4中
            
ORD:        DEC        R4            ;最大比较次数
LOOP:        LCALL    ORDER
            DJNZ    R4,LOOP        ;外层循环
            RET
ORDER:        MOV        A,R4        ;内层比较
            MOV        R2,A
            MOV        A,R3
            MOV        R1,A        ;将给定条件传递给局部变量
LP:            MOV        A,@R1        ;循环取数
            CLR            C            
            INC            R1            ;指针加1
            SUBB        A,@R1
            JC            NEXT1        ;前一个数比后一个小则跳,大于等于则顺下
            ADD        A,@R1        ;恢复前一个数
            MOV        B,@R1        ;备份后一个数
            MOV        @R1,A        ;将前一个数放到后一个数原先的地址处
            DEC        R1            ;指针退到前一个数的位置
            MOV        @R1,B        ;将后一个数放到前一个数原先的地址处
            INC            R1            ;恢复指针
NEXT1:        DJNZ        R2,LP        ;未完则继续
            RET
上程序调试了下,勉强能用,但出口时,R4值改变了,另外,作为一个子程序,它又调了一个子程序,宜乎不规范。
能否修改一下,或者请老师们给个好的,对比学习,更易提高!
            

相关帖子

沙发
wang1987| | 2008-10-8 17:16 | 只看该作者

太乱了

太乱了,都懒的看!用嵌套循环,画出流程图,我这给你一个程序:
      首地址存在R0中,长度在R4中,且按升序排列
RG 0000H
STAR:MOV R0,#40H
     MOV R4,#6H
     DEC R4;别让最后一个数和R4+1个数比较了
 LOOP:MOV A,@R0;取第一个数
      MOV R7,A
      INC R0
      SUBB A,@R0;比较这两个数,第2个数若小则交换
      LCALL PAN;调用判断子程序
      DJNZ R4,LOOP 
      DJNZ R4,STAR
       SJMP$
PAN:  JC NEXT
      MOV A,R7
      XCH A,@R0
      DEC R0
      MOV @R0,A
      INC R0;进行下个数的比较
 NEXT:RET 
END

使用特权

评论回复
板凳
天雨粟|  楼主 | 2008-10-8 19:39 | 只看该作者

疑惑中?

上述程序怎么退出循环呢?
内外循环都用R4控制,C里都用的是两个变量啊!

使用特权

评论回复
地板
天雨粟|  楼主 | 2008-10-11 20:30 | 只看该作者

自己又能思考了一下

出了两天差,路上无事,又思考了一下.二楼网友给了例子是很有参考价值的.
但有两个问题,一是不能作为子程序调用,否则可能限入死循环,二是,虽说首地址放在R0中,但大循环每次将R0初始化为#40H,实为首地址为40H,作为子程序调用是不方便的.
以下根据自己原先的设想,综合二楼的长处,给出一个修改办法,请各位帮看看,是否还可以继续求精,谢先!

;排序子程序
;入口条件,首地址在R3中,数组字节长度在R4中.
;占用工作寄存器R1,R2,R7及累加器A
;出口,给定的数组按升序排列

ORDER:    DEC   R4      ;最大比较次数
LOOP:    MOV   A,R4
    MOV   R2,A
    MOV   A,R3
    MOV   R1,A    ;每次大循环都对地址指针及内循环次数赋值
LP:      MOV   A,@R1   ;取先一个数
    MOV   R7,A    ;备份下来备用
    CLR   C
    INC   R1         ;指向下一个数
    SUBB  A,@R1   ;比较
    JC    NEXT    ;先一个小则跳,大于等于则顺下
    ;ADD  A,@R1
    MOV   A,R7    ;取先一个数
    XCH   A,@R1  ;将先一个放入后一个原先的地址处,后一个备份于A中
    ;MOV  B,@R1
    ;MOV  @R1,A
    DEC   R1         ;指针退一
    ;MOV @R1,B
    MOV  @R1,A    ;将后一个放入先一个原先的地址处
    INC   R1         ;恢复指针
NEXT:    DJNZ  R2,LP   ;未完则继续
    DJNZ  R4,LOOP ;外层循环
    RET

        
            
            

使用特权

评论回复
5
hgjinwei| | 2008-10-12 11:05 | 只看该作者

以下内容纯属捣乱

;// unsigned char型数据排序(由小到大)子程序
;// 入    口 : R0(首地址),R7(数组长度)
;// 出    口 : 待排序数组
;// 使用资源 : ACC,R0,R1,R6,R7
;// 程序影响 : PSW

TAXIS:
    DEC    R7        ;// 最大比较次数为数组长度减一

LOOP:                ;// 外层循环
    MOV    A,R0
    MOV    R1,A      ;// 比较数地址初始化
    MOV    A,R7
    MOV    R6,A      ;// 初始化内层循环次数

LP:                  ;// 内层循环
    INC    R1
    MOV    A,@R1     ;// 由小到大,先取@R1,由大到小先取@R0
    CLR    C
    SUBB   A,@R0
    JNC    NEXT       ;// ACC >= @R0,无须理会
;// ACC < @R0,两数对调
    MOV    A,@R0
    XCH    A,@R1
    MOV    @R0,A
NEXT:
    DJNZ   R6,LP
    INC    R0
    DJNZ   R7,LOOP
EXIT:
    RET

使用特权

评论回复
6
hgjinwei| | 2008-10-12 11:17 | 只看该作者

扩展一下

;// unsigned char型数据排序子程序
;// 入    口 : R0(首地址),R7(数组长度), CY(排序方式,0表示由小到大,1表示由大到小)
;// 出    口 : 待排序数组
;// 使用资源 : ACC,R0,R1,R6,R7
;// 程序影响 : PSW
TAXIS:
    DEC    R7        ;// 最大比较次数为数组长度减一
    MOV    F0,C      ;// 保护入口参数

LOOP:                ;// 外层循环
    MOV    A,R0
    MOV    R1,A
    MOV    A,R7
    MOV    R6,A      ;// 初始化内层循环次数

LP:                  ;// 内层循环
    INC    R1
    CLR    C
    JNB    F0,UP
    MOV    A,@R0
    SUBB   A,@R1
    SJMP   COMP
UP:
    MOV    A,@R1
    SUBB   A,@R0
COMP:
    JNC    NEXT       ;// ACC >= @R0,无须理会
;// ACC < @R0,两数对调
    MOV    A,@R0
    XCH    A,@R1
    MOV    @R0,A
NEXT:
    DJNZ   R6,LP
    INC    R0
    DJNZ   R7,LOOP
EXIT:
    RET

使用特权

评论回复
7
wang1987| | 2008-10-12 11:31 | 只看该作者

讨论讨论

   我的程序修改一下也是可以作为子程序的!至于哪儿出现了死循环,我还是百思不得其解?请高手指点,是SJMP $吗?这只是为调试程序方便而设的,对了4楼的程序我觉得还可以改一下,以下是我根据四楼的程序改编的,我调试过了,可以运行!
   入口条件,首地址在R3中,数组字节长度在R4中
ORDER:DEC   R4     ;最大比较次数
      MOV A,R4
      MOV R6,A
      MOV R2,A
LOOP:MOV   A,R3
    MOV   R1,A    ;每次大循环都对地址指针及内循环次数赋值
LP: MOV   A,@R1   ;取先一个数
    MOV   R7,A    ;备份下来备用
    CLR   C
    INC   R1         ;指向下一个数
    SUBB  A,@R1   ;比较
    JC    NEXT    ;先一个小则跳,大于等于则顺下
    ;ADD  A,@R1
    MOV   A,R7    ;取先一个数
    XCH   A,@R1  ;将先一个放入后一个原先的地址处,后一个备份于A中
    DEC R1
    MOV @R1,A
     INC R1
NEXT: DJNZ  R2,LP   ;未完则继续
      MOV A,R4
      MOV R2,A
    DJNZ  R6,LOOP
     RET

使用特权

评论回复
8
天雨粟|  楼主 | 2008-10-13 18:41 | 只看该作者

感谢大家不吝赐教!

五楼六楼的程序容我再看看!
七楼:关于死循环,SJMP $当然不是问题,是用一个变量控制双重循环,感觉有点问题,应该是不能正常运行的,C里用的是两个。当然这也要请高手帮看看!另外,关于修改,是多增加了一个R6,起什么作用,看不明白!能否细讲讲!

使用特权

评论回复
9
hgjinwei| | 2008-10-13 20:17 | 只看该作者

回复7楼

      DJNZ R4,LOOP 
      DJNZ R4,STAR

这两句连在一起你觉得没问题吗?

使用特权

评论回复
10
天雨粟|  楼主 | 2008-10-13 22:25 | 只看该作者

解读5楼给的程序

;// unsigned char型数据排序(由小到大)子程序
;// 入    口 : R0(首地址),R7(数组长度)
;// 出    口 : 待排序数组
;// 使用资源 : ACC,R0,R1,R6,R7
;// 程序影响 : PSW

TAXIS:
   DEC     R7        ;// 最大比较次数为数组长度减一
LOOP:                  ;// 外层循环
   MOV    A,R0
   MOV    R1,A      ;// 比较数地址初始化
   MOV    A,R7
   MOV    R6,A      ;// 初始化内层循环次数

LP:                  ;// 内层循环
   INC     R1    ;//R1指向下一个数,R0指向每次内循环的首数
   MOV    A,@R1    
   CLR     C
   SUBB   A,@R0
   JNC     NEXT        ;//被比较的数大于等于首地址的数则跳,小于则顺下
   MOV    A,@R0
   XCH    A,@R1
   MOV    @R0,A   ;//形成被比较的数与首地址的数的交换
NEXT:
   DJNZ   R6,LP    ;//每次内循环完成将最小的数放入内循环中的最低位地址
   INC     R0        ;//将低位地址升1
   DJNZ   R7,LOOP ;//R7减1后再传给内循环次数R6
EXIT:
   RET

此程序与我编的算法相反,我的算法是每次将最大数沉底,然后减小内循环的次数,继续沉入操作,当次小数沉入后结束;上程序则是每次将最小数浮到最上(最低位地址处),然后升地址指针,指针指向最高位地址时结束.

使用特权

评论回复
11
天雨粟|  楼主 | 2008-10-13 22:30 | 只看该作者

程序做的还算整齐,怎么贴上去就乱了?

使用特权

评论回复
12
hgjinwei| | 2008-10-14 09:38 | 只看该作者

感谢十楼

十楼楼主的精彩解读让我顿开茅塞啊,以前总奇怪为什么别人都说很难看懂我编写的程序,原来是我写的注释很不清楚.看来还要努力学习啊,不过就要毕业了,还有机会吗?

本来我也是像楼主那样处理的(两两相临比较),但后来发现还要保护首地址(象楼主那样不改变首地址,每次循环时就读首地址也是一种保护),有点慢.就干脆点让首地址数与所有数比较一遍后就不在理会它,这样我就可以不保护了.

使用特权

评论回复
13
红心j| | 2008-10-14 13:22 | 只看该作者

瞎做一个:

SUB:            MOV     A,R4
                DEC     A
                MOV     R6,A
SUB_LOOP:       MOV     A,R4
                DEC     A
                MOV     R5,A
                MOV     A,R3
                MOV     R0,A
                INC     A
                MOV     R1,A

SUB_LOOP1:      MOV     A,@R0
                CLR     C
                SUBB    A,@R1
                JC      SUB_LOOP1_1
                MOV     A,@R0
                XCH     A,@R1
                XCH     A,@R0
SUB_LOOP1_1:    INC     R0
                INC     R1
                DJNZ    R5,SUB_LOOP1
                DJNZ    R6,SUB_LOOP
                RET

使用特权

评论回复
14
天雨粟|  楼主 | 2008-10-14 19:17 | 只看该作者

十二楼

注释是写给自己看的,自己清楚就可以了,你去看大师给的例程,同样是了了数语,提纲挈领--除非你是在写教材,或者是像我种自学者,试图印证一下.

源程序就是王道,注释是小道,如果注释就能说清楚一个程序算法,则文学家就要抢程序员的饭碗,呵呵!

使用特权

评论回复
15
天雨粟|  楼主 | 2008-10-14 21:09 | 只看该作者

十三楼的程序应可运行

由于内循环次数固定,使得算法较简便,但代价是要进行一些无效的比较。排序算法吸引人的地方在于:内循环一遍,外循环次数减一;外循环一次,内循环控制变量减一。互相牵制,随形俯仰,丝丝入扣。
这在C里看得最为清楚:

#include <REGX52.H>
#define N 10

unsigned char array[10]={0x10,0x12,0x20,0x80,0x60,0x40,0x0,0x0,0x0,0x0};

 main(){
    unsigned char temp;
    unsigned char i,j;
    for(i=0;i<N-1;i++)
            for(j=0;j<N-1-i;j++)
            if(array[j]>array[j+1]){
                   temp=array[j];
                   array[j]=array[j+1];
                   array[j+1]=temp;
                   }
      while(1);
    }

使用特权

评论回复
16
天雨粟|  楼主 | 2008-10-19 09:51 | 只看该作者

大师给的排序算法

大师给的排序算法,确属不凡
刚才查资料,偶见了一个排序算法,确然细致精当,贴出来共享。

入口条件:数据块的首址在R0中,字节数在R7中;
出口信息:完成排序(增序);
影响资源:PSW,A,R2~R6;堆栈需求:2字节
(注释为笔者所加,非大师原注)
SORT:
     MOV     A,R7    
     MOV     R5,A     ;字节长度备份在R5中,出口时R7值不变
SRT1: 
     CLR     F0       ;引入标志,后见妙用
     MOV     A,R5    
     DEC     A
     MOV     R5,A    ;R5实为外循环次数
     MOV     R2,A    ;R2实为内循环次数
                  ;R2与R5同步,形成内循环一遍,外循环次数减一;
        ;外循环一次,内循环循环次数少一
     JZ   SRT5    ;与减一不为0则继续循环的DJNZ指令功用相同
     MOV     A,R0    ;指针R0有增减,后又要用其初值,固用R6备份它
     MOV     R6,A
SRT2:
     MOV  A,@R0    ;取先一个数
     MOV     R3,A    ;可能被交换,固先备份它
     INC     R0
     MOV     A,@R0    ;取后一个数
     MOV     R4,A    ;为了交换,先备份它
     CLR        C
     SUBB     A,R3    ;后一个数减先一个数
     JNC     SRT4    ;无借位的话跳,继续内循环
     SET     F0        ;凡后一个数小则置标志位
     MOV     A,R3    ;
     MOV     @R0,A    ;先一个放入后一个原先的地址处
     DEC     R0        ;指针退一
     MOV     A,R4    ;取后一个数
     MOV     @R0,A    ;后一个数放入先一个原先的地址处
     INC     R0        ;恢复指针
SRT4:
     DJNZ R2,SRT2    ;内循环未完则继续
     MOV     A,R6
     MOV     R0,A    ;恢复首地址指针,出口时R0的值不变
     JB     F0,SRT1    ;内循环结束后如果未进行哪怕一次交换
SRT5:        ;则结束排序,因数据已符合顺序,固break循环
     RET        ;以节省运算时间
        

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

168

帖子

0

粉丝