目的与要求
内容与方法
步骤与过程
程序总体设计
核心数据结构-冒泡排序
调试过程
成绩数据文件data初始编写和程序数据
成绩复制
冒泡排序
A B计数保存
核心代码
结论或体会
目的与要求
分析和理解实验中指定的问题
利用LC-3.汇编代码设计实现相关程序
熟练掌握循环支程序设计方法
内容与方法
- 背景
- 16名学生的成绩排名和统计分析
- 分类规则
- A:全班前25%,成绩85分以上
- B:非A分,全班前50%,75分以上
- C:非A、B成绩
- 要求
- 使用LC-3汇编语言,编写程序实现上述功能
- 输入
- 16名学生的成绩存储在x3200至x320F
- 每个分数在0到100之间,由16比特无符号整数表示
- 输出
- 成绩降序排序,并存储在x4000至x400F内存位置,x4000位置成绩最高
- 得A、B成绩的学生总人数,分别存储于x4100,及x4101位置
步骤与过程
- 根据主题,首先要实现的是结果的存储。首先,我使用标签SCORE存储结果的第一个地址x3200,用data在起始位置记录了16个成绩:.ORIG x3200。
- 其他重要地址和常用标号如下:
SCORE .FILL x3200 ;成绩存储的起始地址 RES .FILL x4000 ;成绩降序结果存储起始地址 Anum .FILL x4100 ;存放A地址 Bnum .FILL x4101 nAscore .FILL -85 ;A分数相反数 nBscore .FILL -75 StuNUM .FILL 16 ;学生人数 ONE .FILL 1 ;1
- 具体实现步骤如下:
- 将结果复制到结果区:COPY循环
- 泡沫排序:2层嵌套循环
- 计算A B人数:每两个循环(CountA CountB)
- 结果保存:STORE
C 代码如下:
for(int i=1;i<n;i ){ For(int j=0;j<n-I;j ){ If(score[j]<score[j 1]){ Swap(score[j],score[j 1]) } } }
由于程序步骤较多,我逐步完成了模块编写和调试。
R1存成绩存放初始地址SCORE(x3200),R7存结果降序成绩初始地址RES(x4000)。标号编写。

Figure 1 data编写和程序数据初始
运行结果无误(图 2 )
Figure 2 数据获得和初始成功
成绩复制
先将成绩直接复制到结果区,在结果区排序。
编写编译运行(图 3 )
Figure 3 成绩复制代码编译运行
结果正确, x3200 和 x4000 存放的数据一样(图 4 )
Figure 4 成绩复制成功
冒泡排序
编译通过(图 5 )
Figure 5 冒泡成功编译运行
答案错误,代码有误,经过单步调试发现是每轮冒泡循环没有把成绩指针指向首位。(图 6 )
Figure 6 调试过程
修改代码(图 7 )
每次循环都初始成绩指针指向第一个成绩。修改后答案正确
Figure 7 修改冒泡排序
A B 计数保存
2个循环CountA和CountB遍历前4和前8个数,获得A B人数,并保存。
Figure 8 程序结果正确
核心代码
.ORIG x3000 ;程序开始
LD R1,SCORE ;R1为存放成绩初始地址
LD R7,RES ;R7存放成绩降序结果地址
LD R2,StuNUM ;R2装入学生人数
;
; 成绩复制至结果区(loop)
;
COPY LDR R3,R1,0 ;R3存成绩
STR R3,R7,0 ;成绩存结果
ADD R1,R1,1 ;下一个成绩
ADD R7,R7,1 ;结果成绩指针移向下一个
ADD R2,R2,-1 ;计数减1
BRp COPY ;继续循环直至全部复制
; 冒泡排序
;
LD R2,ONE ;R2初始1,外层循环i,轮次
;
; 外层循环LOOP1(R2 0<i<n)
LOOP1
; 内层循环(R3 0<=j<n-i)
;
LD R7,RES ;R7存放成绩降序结果首地址
AND R3,R3,0 ;R3清零, 里层循环j,下标
ADD R1,R2,-16 ;R1=-(n-i)
LOOP2 LDR R4,R7,0 ;R4存SCORE[j]
LDR R5,R7,1 ;R5存SCORE[j+1]
NOT R6,R4
ADD R6,R6,1
ADD R6,R6,R5 ;R6=SCORE[j+1]-SCORE[j]
BRnz FLAG ;如果SCORE[j+1]<=SCORE[j],不用交换直接跳过
;
; 交换SCORE[j+1] SCORE[j]
;
STR R5,R7,0
STR R4,R7,1
;
FLAG
ADD R7,R7,1 ;指向下一成绩
ADD R3,R3,1 ;j++
ADD R6,R3,R1 ;R6=j-(n-i)
BRn LOOP2 ;如果j<n-i,继续内层循环
;
; 内层循环结束
ADD R2,R2,1
ADD R6,R2,-16;R6=i-n
BRn LOOP1 ;如果i<n,继续外层循环
;
; 外层循环结束,冒泡排序完成
; 计数A B人数
;
LD R2,nAscore ;R2=-85
LD R3,nBscore
AND R1,R1,0 ;R1清零,计数
AND R5,R5,0 ;R5清零存A人数
AND R6,R6,0 ;B人数
LD R7,RES ;R7存放成绩降序结果首地址
;
; 获得的A人数
;
CountA LDR R4,R7,0
ADD R4,R4,R2 ;R4=score-85
BRn CountB ;如果score<85,开始计数B
ADD R5,R5,1 ;人数增加
ADD R7,R7,1 ;移向下一分数
ADD R1,R1,1 ;计数加1
ADD R0,R1,-4 ;R0=计数-4
BRn CountA ;计数小于4,还在前25%继续判断A人数
;
; 获得B的人数
;
CountB LDR R4,R7,0
ADD R4,R4,R3 ;R4=score-75
BRn STORE ;如果score<75,跳出B计数,进行保存
ADD R6,R6,1 ;人数增加
ADD R7,R7,1 ;移向下一分数
ADD R1,R1,1 ;计数加1
ADD R0,R1,-8 ;R0=计数-8
BRn CountB ;计数小于8,还在前50%继续判断B人数
;
; 将A B人数保存
;
STORE STI R5,Anum
STI R6,Bnum
HALT ;程序运行结束
;
SCORE .FILL x3200 ;成绩存放起始地址
RES .FILL x4000 ;成绩降序结果存放起始地址
Anum .FILL x4100 ;存放A地址
Bnum .FILL x4101
nAscore .FILL -85 ;A分数相反数
nBscore .FILL -75
StuNUM .FILL 16 ;学生人数
ONE .FILL 1 ;1
;
.END ;代码结束
结论或体会
在本次实验中,我首次尝试了在LC3利用汇编代码实现一个小程序,熟悉了了相关语法和良好的代码分割。认识到了适用标号的诸多好处,如利用LD直接加载数据常量,将地址偏移的计算交给机器负责从而增加代码的可读性;同时也熟悉了关于标号的各种操作。通过规定文件起始位置(.ORIG)实现多文件连接的可能。
另外我熟悉了利用汇编代码编写循环和分支结构的过程,第一次尝试用汇编代码实现冒泡排序。尝试了将一个实际问题通过问题分析,找到相应的算法实现流程及数据结构,进而通过逐步编写调试完成对问题的解决。
在本次实验中我也纠正了一些自己的模糊认知。比如标号地址是一个常量,不能做指针移动。其他数据标号也同样是常量,需要将其赋值给寄存器才能进行变量操作。另外lc3仅有8个寄存器。需要合理循环利用寄存器。