- 编写子程序paixu,实现1Byte数的顺序排列。待排序的10个二进制数(自定义数据大小)存放在内存空间内。
- 编写宏定义实现大小比较和换位,入口参数为待比较的两个数据地址。
- 注意排序过程中需要使用间接寻址方式,即利用FSR和INDF两个特殊功能寄存器实现寻址操作。
- 编写子程序,调用宏定义,使用冒泡排序算法实现排序。
1、冒泡排序算法
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
冒泡排序算法的运作如下:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
2、编写宏定义实现大小比较与换位
程序框图
:
;*****************宏定义*********************************************************
compare_swap macro DATAI,DATAJ,TEMP
BCF STATUS,C ; 标志位清零
MOVF DATAJ,W
SUBWF DATAI,W ; 比较大小
BTFSC STATUS,C ; TEMP1>TEMP2?
GOTO NEXT1
GOTO NEXT2
NEXT1
swap DATAI,DATAJ,TEMP ; 是,则交换两者的值
NEXT2
nop ; 否则,不做操作
endm
swap macro DATAI,DATAJ,TEMP
MOVF DATAI,W
MOVWF TEMP
MOVF DATAJ,W
MOVWF DATAI
MOVF TEMP,W
MOVWF DATAJ
endm
进行宏指令嵌套时,要十分注意宏指令调用与子程序调用的区别,否则很容易产生错误。例如下面这段代码:
BTFSC STATUS,C ; TEMP1>TEMP2?
GOTO NEXT1
GOTO NEXT2
NEXT1
swap DATAI,DATAJ,TEMP ; 是,则交换两者的值
NEXT2
nop
如不慎写作:
BTFSC STATUS,C ; TEMP1>TEMP2?
swap DATAI,DATAJ,TEMP ; 是,则交换两者的值
nop ; 否则,不做操作
就会发生错误。
3、编写子程序,调用宏定义实现排序
子程序框图:
;*************************子程序************************** ********************
ORG 0x0100
paixu
LOOP1
MOVLW 0x20
MOVWF FSR ; FSR=0x20,起始位置
CLRF COUNT2
LOOP2
MOVF INDF,W
MOVWF DATAI
INCF FSR,F
MOVF INDF,W
MOVWF DATAJ
compare_swap DATAI,DATAJ,TEMP
MOVF DATAJ,W ; 数据还原
MOVWF INDF
DECF FSR,F
MOVF DATAI,W
MOVWF INDF
INCF FSR,F
INCF COUNT2,F ; COUNT2++,COUNT2<9-COUNT1?
MOVF COUNT1,W
SUBWF SIZE,W
BSF STATUS,C
SUBWF COUNT2,W
BTFSS STATUS,C
GOTO LOOP2
INCF COUNT1,F ; COUNT1++,COUNT1<9?
BSF STATUS,C
MOVF SIZE,W
SUBWF COUNT1,W
BTFSS STATUS,C
GOTO LOOP1
NOP
RETURN
;*****************************************************************************
附
完整程序:
list p=16f877A ;标明所用的处理器类型
#include ;调用头文件
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _HS_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF
;*****************宏定义*********************************************************
compare_swap macro DATAI,DATAJ,TEMP
BCF STATUS,C ; 标志位清零
MOVF DATAJ,W
SUBWF DATAI,W ; 比较大小
BTFSC STATUS,C ; TEMP1>TEMP2?
GOTO NEXT1
GOTO NEXT2
NEXT1
swap DATAI,DATAJ,TEMP ; 是,则交换两者的值
NEXT2
nop ; 否则,不做操作
endm
swap macro DATAI,DATAJ,TEMP
MOVF DATAI,W
MOVWF TEMP
MOVF DATAJ,W
MOVWF DATAI
MOVF TEMP,W
MOVWF DATAJ
endm
;*****************变量定义*******************************************************
DATA1 EQU 0x20 ; 待排序的数据
DATA2 EQU 0x21
DATA3 EQU 0x22
DATA4 EQU 0x23
DATA5 EQU 0x24
DATA6 EQU 0x25
DATA7 EQU 0x26
DATA8 EQU 0x27
DATA9 EQU 0x28
DATA10 EQU 0x29
SIZE EQU 0x30 ; 待排序数据个数-1
COUNT1 EQU 0x31 ; 循环变量
COUNT2 EQU 0x32
TEMP EQU 0x33 ; 临时变量
DATAI EQU 0x34
DATAJ EQU 0x35
;*******************************************************************************
ORG 0x0000 ; 复位入口地址
nop ; 兼容ICD调试工具,必须加nop
goto Main ; 跳转至Main函数
;*************************Main 函数的代码***************************************
Main
MOVLW 0x34 ; 数据初始化
MOVWF DATA1
MOVLW 0x53
MOVWF DATA2
MOVLW 0xb5
MOVWF DATA3
MOVLW 0x33
MOVWF DATA4
MOVLW 0xA1
MOVWF DATA5
MOVLW 0x42
MOVWF DATA6
MOVLW 0x11
MOVWF DATA7
MOVLW 0x86
MOVWF DATA8
MOVLW 0x65
MOVWF DATA9
MOVLW 0x76
MOVWF DATA10
MOVLW .9
MOVWF SIZE
CLRF COUNT1 ; 初始化循环变量
CLRF COUNT2
CLRF TEMP ; 初始化临时变量
CLRF DATAI
CLRF DATAJ
CALL paixu ; 调用子程序排序
nop
goto $ ; 停机
;*************************子程序************************** ********************
ORG 0x0100
paixu
LOOP1
MOVLW 0x20
MOVWF FSR ; FSR=0x20,起始位置
CLRF COUNT2
LOOP2
MOVF INDF,W
MOVWF DATAI
INCF FSR,F
MOVF INDF,W
MOVWF DATAJ
compare_swap DATAI,DATAJ,TEMP
MOVF DATAJ,W ; 数据还原
MOVWF INDF
DECF FSR,F
MOVF DATAI,W
MOVWF INDF
INCF FSR,F
INCF COUNT2,F ; COUNT2++,COUNT2<9-COUNT1?
MOVF COUNT1,W
SUBWF SIZE,W
BSF STATUS,C
SUBWF COUNT2,W
BTFSS STATUS,C
GOTO LOOP2
INCF COUNT1,F ; COUNT1++,COUNT1<9?
BSF STATUS,C
MOVF SIZE,W
SUBWF COUNT1,W
BTFSS STATUS,C
GOTO LOOP1
NOP
RETURN
;*****************************************************************************
END ; 程序结束