C51 汇编语言冒泡排序的实现
1.整体思路
冒泡排序C语言代码如下:
void bubble_sort(int arr[], int len) {
int i, j, temp;
for (i = 0; i < len - 1; i++)
for (j = 0; j < len - 1 - i; j++)
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
为实现此程序,可以利用两个寄存器充当i和j,对于i的上限的判断,直接利用CJNE指令判断当i不为4(预存5个数字)的时候跳转继续排序。对于j的上限,由于8051单片机没有相等时转移的指令,可以利用减法所得是否为0来判断j是否到达上限,以及对j的清空。
循环过程内,利用MOVX指令配合A和R0以及DPTR实现数据的读取。取得的两数据间的大小比较用减法指令实现,利用进位标志位判断是否需要进行交换。对于从大到小排和从小到大排的切换在同一个子程序内实现,只需利用JB和JNB指令判断7AH的取值(7AH的值决定是正序排序还是倒序排序)以决定是否需要对取得的两个数据进行交换。以此实现两种排序方式的切换。
程序源码:
ORG 0000H
LJMP MAIN
ORG 2000H
MAIN:
SRC DATA 30H ;写入数字的起始地址
DEST XDATA 2000H ;逆序拷贝数字的起始地址
NUM DATA 20H ;写入的数字的数量的地址
CLR 20H ;初值为0个数字
MOV 10H, #03H
MOV 11H, #04H
MOV 12H, #01H
MOV 13H, #02H
MOV 14H, #05H
MOV 15H, #24H ;预存的数字,其中24H为结束符$
MOV R0, #10H
MOV R1, #SRC ;定位至SRC内存
MOV R2, #0H ;定义i=0
MOV R3, #0H ;定义j=0
ACALL Write_In ;跳转至写入模块
MOV DPTR, #DEST ;将外部存储器地址传入DPTR
ACALL Write_Out ;跳转至拷贝模块
CLR 7AH ;从小到大排序
MOV DPTR, #DEST ;回溯DPTR
ACALL ORDERS ;冒泡排序子程序
SETB 7AH ;从大到小排序
ACALL ORDERS ;冒泡排序子程序
SJMP $
Write_In:
MOV A, @R0
MOV @R1, A ;复制预存的数字到SRC所在的地址中
INC NUM ;存储的数字的数量加1
INC R0
INC R1 ;R1(#SRC)加1
CJNE @R0, #24H, Write_In ;未捕捉到结束符就继续写入数字
RET
Write_Out:
DEC R1 ;回到$字符的上一个数字的地址
DEC NUM
MOV A, @R1
MOVX @DPTR, A ;拷贝回片外地址
INC DPTR ;地址加1
MOV R0, NUM
CJNE R0, #0H, Write_Out ;剩余数字的数量不为0就继续拷贝
RET
ORDERS: ;冒泡排序
MOV A, #05H
CLR C
SUBB A, R2
DEC A
CLR C
SUBB A, R3 ;A = j-(5-i-1)
CJNE A, #0H, JPLUS ;若j=5-i-1则清空j
MOV R3, #0H ;清空J
MOV DPTR, #DEST ;回溯DPTR
INC R2 ;i++
CJNE R2, #04H, ORDERS ;i不为4就继续排序
MOV R2, #0H ;清空i,为从高到低排序做准备
RET
JPLUS:
MOVX A, @DPTR
MOV R0, A
INC DPTR
INC R3 ;J++
MOVX A, @DPTR
JNB 7AH, UpsideDown ;若7AH等于0,则从低到高排序
XCH A, R0 ;交换a[J]与a[J+1]
MOV R4, A ;保护A内的数据
UpsideDown:
CLR C
SUBB A, R0
JC SWAP1 ;若a[J]>a[J+1]则转移,即判断进位标志位
SJMP ORDERS
SWAP1:
JNB 7AH, JUMP ;若7AH等于0则跳过
MOV A, R4
MOV R0, A ;若7AH等于1,则需恢复A与R0
JUMP:
MOVX A, @DPTR
XCH A, R0 ;交换a[J]与a[J+1]
MOVX @DPTR, A
DEC DPL ;DPTR低位减一
MOV A, R0
MOVX @DPTR, A ;将交换完的数据传回片外RAM
INC DPTR ;恢复减去的DPTR
SJMP ORDERS
实现效果
片外RAM中起初存储的数字序列为5 2 1 4 3
排序后效果应当如下:
2 1 4 3 5
1 2 3 4 5
1 2 3 4 5
第三趟时则已完成排序。
将排序好的序列再从大到小排,
以此为:
2 3 4 5 1
3 4 5 2 1
4 5 3 2 1
5 4 3 2 1