C51 汇编语言冒泡排序的实现

本文详细介绍了在8051单片机上使用C语言实现冒泡排序的步骤,包括利用寄存器优化、数据读取方法、比较和交换操作,以及两种排序方式(正序和倒序)的切换。初始数字序列52143经过冒泡排序后变为12345和21435。
摘要由CSDN通过智能技术生成

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

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值