汇编:冒泡排序算法的实现

发布于:2025-05-22 ⋅ 阅读:(25) ⋅ 点赞:(0)

一、 实验要求

实验目的:

  1. 学习使用汇编语言实现算法设计
  2. 熟练掌握单片机外部存储空间的访问方法

实验内容:

  1. 用汇编实现冒泡排序算法。
  2. 在实验三的代码基础上,利用冒泡排序将DEST中数据从小到大重新排序 。
  3. 将冒泡排序算法写成子程序。
  4. 在主程序中,通过设置参数,使用同一个子程序实现从大到小,从小到大排序的自由选择。

二、 实验设计

 1.整体思路

对一段数据进行排序,根据7AH寄存器的值决定是从小到大还是从大到小排序。代码主要分为两个子模块:STOB和BTOS。

2.流程图

     

3.主要模块设计思路及分析

(1)STOB子程序

  1. 初始化R2和R3为0,用于外层循环计数和内层循环计数。
  2. 设置R4为NUM,用作循环次数。
  3. 外层循环(Outer_STOB):通过R4计数,控制排序轮次。
  4. 内层循环(Inner_STOB):通过R5计数,控制每轮排序的比较次数。
  5. 从DPTR指向的内存中读取数据并进行比较。
  6. 如果当前字节小于上一个字节,进行交换。
  7. 继续内层循环直至完成当前轮次的比较。
  8. 继续外层循环直至完成所有轮次的比较。

(2)BTOS子程序

  1. 初始化R2和R3为0,用于外层循环计数和内层循环计数。
  2. 设置R4为NUM,用作循环次数。
  3. 外层循环(Outer_BTOS):通过R4计数,控制排序轮次。
  4. 内层循环(Inner_BTOS):通过R5计数,控制每轮排序的比较次数。
  5. 从DPTR指向的内存中读取数据并进行比较。
  6. 如果当前字节大于上一个字节,进行交换。
  7. 继续内层循环直至完成当前轮次的比较。
  8. 继续外层循环直至完成所有轮次的比较。

              

三、 实现效果 

由大到小

由小到大

四、总结

1.在本次冒泡排序的实验中,参考了C语言的代码思路,采用内外循环的方法来实现内外循环。

2.在实验最开始思考如何进行两个数据大小的比较,发现汇编指令里有的指令无法再K4里执行,最后采用减法来判断两个数据的大小。

3.关于上一个实验程序,不知道是因为代码错误还是思路错误的原因,出现死循环,于是我在程序中添加了一行代码。当LOOP1与LOOP2执行完后,直接跳转到冒泡排序的子程序。

4.本次实验让我掌握了单片机外部存储空间的访问方法。

附录:

ORG 0000H
	LJMP MAIN
	
	ORG 2000H

MAIN:
    SRC DATA 30H
    DEST XDATA 2000H
    NUM DATA 20H

    MOV A, #01H           ; 将值01H存储到A寄存器中
    MOV R0, #SRC
    MOV DPTR, #DEST
    MOV R2, #NUM
    MOV R3, #NUM
    ACALL LOOP1
    DEC R0                ; LOOP1 子程序中R0最后多加了一次,所以要减1
    ACALL LOOP2

CHECK:
    CJNE R2, #0, CHECK    ; 检查R2是否为0,如果不为0则继续循环,避免成为死循环

LOOP1:
    MOV @R0, A            ; 将A寄存器的值存储到R0指向的地址
    INC R0 
    ADD A, #01H
    DJNZ R2, LOOP1        ; 如果R2不等于0,则跳转到LOOP1继续执行循环
    RET

LOOP2:
    MOV A, @R0            ; 将R0指向的地址的值存储到A寄存器
    DEC R0
    MOVX @DPTR, A
    INC DPTR
    DJNZ R3, LOOP2        ; 如果R3不等于0,则跳转到LOOP2继续执行循环
    RET

NEXT: SJMP MAIN1          ; 跳入冒泡循环子程序

MAIN1:
    CLR		7AH
    ACALL	ORDERS
    SETB	7AH 
    ACALL	ORDERS
    SJMP $

ORDERS:
    CLR C
    JB 7AH, BTOS          ; 如果 7AH 置位(非零),则进行从大到小排序
    ACALL STOB            ; 否则进行从小到大排序
    SJMP ENG

STOB:
    MOV R2, #0            ; R2 用于外层循环计数
    MOV R3, #0            ; R3 用于内层循环计数
    MOV R4, #NUM

Outer_STOB:
	MOV A,R4
	MOV R5, A
	DEC R5                ; R5 存储当前轮次内循环次数
	MOV R6, #0            ; R6 用于比较次数计数

Inner_STOB:
	MOVX A, @DPTR
	INC DPTR
	MOV R7, A 
	
	MOVX A, @DPTR
	SUBB A, R7            ; 与上一个字节的数据进行比较
	JC Skip_STOB          ; 如果 A < 上一个字节的数据,跳过交换
	
	XCH A, R7 
	MOVX @DPTR, A
	MOV A, R7
	
	INC R6
	
Skip_STOB:
	DJNZ R5, Inner_STOB
	DJNZ R4, Outer_STOB
	
	SJMP ENG	

BTOS:
	MOV R2, #0            ; R2 用于外层循环计数
	MOV R3, #0            ; R3 用于内层循环计数
	MOV R4, #NUM

Outer_BTOS:
	MOV A,R4
	MOV R5, A
	DEC R5                ; R5 存储当前轮次内循环次数
	MOV R6, #0            ; R6 用于比较次数计数

Inner_BTOS:
	MOVX A, @DPTR
	INC DPTR
	MOV R7, A
	
	MOVX A, @DPTR
	SUBB A, R7            ; 与上一个字节的数据进行比较
	JNC Skip_BTOS         ; 如果 A > 上一个字节的数据,跳过交换
	
	XCH A, R7
	MOVX @DPTR, A
	MOV A, R7
	
	INC R6 
	
Skip_BTOS:
	DJNZ R5, Inner_BTOS
	DJNZ R4, Outer_BTOS
	
ENG:
    END


网站公告

今日签到

点亮在社区的每一天
去签到