实验内容

将片内 RAM 30H 开始的 32 个单元中分布着随机的有符号 8 位二进制数,请按从小到大的顺序进行排序,排序后的数据仍然保存到 30H 开始的 32 个单元中(低地址存放小数据)。

编程思路

首先,在程序存储器中构建一个表格,该表格具有 32 个随机产生的 8 位二进制数,如:

TABLE: DB 1,3,9,2,17,4,11,6

DB 5,20,100,64,21,14,79,35

DB 92,7,91,23,65,16,13,18

DB 18,73,65,101,27,19,62,69

然后利用查表指令“MOVC A,@A+DPTR”将它们读取到 30H-4FH 单元中,然后再利用“冒泡法排序法”将它们排序即可。“冒泡法排序法”的基本原理是:

遍历所有 32 个数据找出其中的最大者,并记下最大数据所在的存储位置,然后将这个最大的数据放置在最后一个单元,同时,将最后一个单元原来的数据保存到这个最大值原来所处的位置,完成第一轮的排序。

然后,再遍历除了最后一个单元以外的前面 31 个单元的数据并找出其中最大者,并记下其所在位置,遍历完这一遍后将找到的最大数据保存在倒数第二个单元(对于所有数据来说它是次最大数据,所以保存在倒数第二个单元),并将倒数第二个单元原来的数据保存在刚刚找到的那个最大值原来所在的位置处,完成第二轮的排序。依次类推,用同样的方法把

所有的数据排好序即可。

流程图

image-20220212122619751

实验过程

① 根据上述实验内容及程序流程图,编写汇编语言源程序,并加上相应注释,注意扩展名为“*.asm”,将其保存。

② 运行 Keil uVision2 开发环境,按照 1.1.3 节介绍的方法建立工程 simlab2.uV2,CPU为 AT89C51,不用包含启动文件 STARTUP.A51。

③ 编写好的源程序加入工程 simlab2.uV2,并设置工程 simlab2.uV2 属性,将其晶振频率设置为 12MHz,选择输出可执行文件,仿真方式为“Use Simulator”。

④ 构造(Build)工程 simlab2.uV2。如果输入有误进行修改,直至构造正确,生成可执行程序 simlab2.hex 为止。

⑤ 运行程序,并用存储器观察窗口,观察内部 RAM 30H-4FH 单元排序前后的数值。将表格中的32个随机排列的8位二进制数据搬移到30H开始的32个内部RAM单元中:

img

排序后:

img

实验源程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
ORG 0000H
AJMP START           ;跳转到程序开始的地方

ORG 0100H
START:               ;程序入口
      MOV DPTR,#TABLE     ;将表格入口地址传送给DPTR
      MOV R1,#20H          
      MOV R0,#4FH          
TRANS:                      
     MOV A,R1
     DEC A
     MOVC A,@A+DPTR
     MOV @R0,A
     DEC R0
     DJNZ R1,TRANS
;上面完成了程序存储器的32个单元的数据搬移
     MOV R2,#4FH           ;R2 = 4FH
CMP1: MOV R1,#30H           ;R1 = 30H
     
CMP2: MOV A,R1             ;前一个数据的地址传给A
      INC A                ;A = A+1
      MOV R0,A             ;将后一个数据对的地址传给R0

      CLR C                ;将Cy置零
      MOV A,@R1           ;将前一个数据传给A
      SUBB A,@R0           ;用前一个数减后一个数
MOV A,@R1
      JNC EXCHG            ;根据上面的减法指令得到的Cy判断是否转移到交换子程序           如果前面一个数大于后一个数,则Cy=0,则说明满足冒泡,跳转到交换子程序;反之继续往下运行
      SJMP INC1            ;如果Cy=1,则跳过交换子程序,跳转到INC1子程序

EXCHG: XCH A,@R0           ;该交换子程序用于交换数据
      MOV @R1,A

INC1: INC R1               ;R1 = R1+1
      CLR C                ;Cy置零
      MOV A,R1             ;A = R1
      SUBB A,R2            ;减法指令A-R2,主要是用来判断下一个冒泡数据的位置
      JC CMP2              ;如果减法指令使得Cy=0(R1>=R2),那说明将要进行冒泡算法的数据为最后一个数,则不需要冒泡,则会运行到DEC1;反之则当前数据需要继续进行冒泡,跳转到CMP2
DEC1: DEC R2               ;R2 = R2 -1         每完成一轮冒泡,就说明后排多了一个固定数,不需要和固定的大数比较,可以减少数据的处理
      CJNE R2,#30H,CMP1   ;判断R2和30H是否不相等。当R2不相等时,则说明有数据需要继续冒泡;否则说明冒泡算法已经结束。

ORG 3000H                  
TABLE: DB 1,3,9,2,17,4,11,6
DB 5,20,100,64,21,14,79,35
DB 92,7,91,23,65,16,13,18
DB 18,73,65,101,27,19,62,69
END