深圳大学-计算机系统(1)实验-求成绩等级

实验内容

在这里插入图片描述

实验数据

4000  ;数据在内存地址4000处开始
004A
0055
003C
003D
0049
0054
0064
0026
0042
0035
004C
0052
0048
005F
004A
0050

实验代码

.ORIG x3000

; 初始化寄存器
AND R0, R0, #0
AND R1, R1, #0
AND R2, R2, #0
AND R3, R3, #0
AND R4, R4, #0
AND R5, R5, #0
AND R6, R6, #0
AND R7, R7, #0

; 复制成绩数据到 x5000
LD R1, SOURCE_ADDR  ; 成绩源地址 x4000
LD R2, DEST_ADDR    ; 目标地址 x5000
LD R3, NUM_16       ; 成绩数量

COPY_LOOP
    LDR R4, R1, #0  ; 从 R1 处加载数据到 R4
    STR R4, R2, #0  ; 存储 R4 到 R2 处
    ADD R1, R1, #1  ; 增加 R1 地址
    ADD R2, R2, #1  ; 增加 R2 地址
    ADD R3, R3, #-1 ; 减少计数器 R3
    BRp COPY_LOOP   ; 如果 R3 > 0,继续循环



; 冒泡排序成绩
LD R1, NUM_16         ; 外层循环计数器

SORT_OUTER_LOOP
    ADD R1, R1, #-1   ; 外循环计数器-1
    BRz CALC_GRADES   ; 如果 R1==0,结束外循环

    ; 内层循环
    LD R2, DEST_ADDR
    ADD R3, R1, #0    ; 内层循环计数器初始化

SORT_INNER_LOOP
    ADD R4, R2, #1    ; R4 设置为下一个地址
    LDR R5, R2, #0    ; 从 R2 处加载当前成绩到 R5
    LDR R6, R4, #0    ; 从 R4 处加载下一个成绩到 R6

    ; 如果当前成绩大于下一个成绩,交换它们
    NOT R7, R5
    ADD R7, R7, R6
    BRzp NOSWAP       ; 如果 R5 <= R6,不交换
    STR R6, R2, #0    ; 否则,交换 R5 和 R6
    STR R5, R4, #0

NOSWAP
    ADD R2, R2, #1    ; 增加内循环地址 R2
    ADD R3, R3, #-1   ; 内循环计数器-1
    BRp SORT_INNER_LOOP ; 内层循环未结束

    BRnzp SORT_OUTER_LOOP ; 外层循环继续


; 计算成绩等级
CALC_GRADES
LD R0, DEST_END_ADDR   ; 将 R0 设为排序后的最后一个数据地址 (x500F)
AND R4, R4, #0         ; 清零 A 等级计数器
AND R5, R5, #0         ; 清零 B 等级计数器
AND R6, R6, #0         ; 清零学生计数器
AND R7, R7, #0

LD R1, NUM_16          ; 总成绩数量 (16)

GRADE_LOOP
    LDR R2, R0, #0     ; 从 R0 处加载当前成绩到 R2
    ADD R0, R0, #-1    ; R0 地址减少 (倒序遍历)
    ADD R6, R6, #1     ; 学生计数器增加

    ; 判断是否在前 25% 且 >= 85
    LD R3, A_THRESH
    NOT R3, R3
    ADD R3, R3, #1     ; 
    ADD R3, R3, R2     ; 判断 R2 - A_THRESH (即 R2 是否 >= 85)
    BRn CHECK_B        ; 如果成绩 < 85 跳到 CHECK_B
    ADD R7, R6, #-5    ; 比较计数器值,如果值 <= 4 即前25%学生
    BRp CHECK_B        ; 如果计数器值大于4,则跳到 CHECK_B

    ; 成绩在前 25% 且 >= 85
    ADD R4, R4, #1     ; A 等级计数加 1
    BRnzp GRADE_NEXT   ; 跳到下一个成绩

CHECK_B
    ; 判断是否在前 50% 且 >= 75
    LD R3, B_THRESH
    NOT R3, R3
    ADD R3, R3, #1     ; 
    ADD R3, R3, R2     ; 判断 R2 - B_THRESH (即 R2 是否 >= 75)
    BRn GRADE_NEXT     ; 如果成绩 < 75 跳到 GRADE_NEXT
    ADD R7, R6, #-9    ; 比较计数器值,如果值 <= 8 即前50%学生
    BRp GRADE_NEXT     ; 如果计数器值大于8,则跳到 GRADE_NEXT

    ; 成绩在前 50% 且 >= 75
    ADD R5, R5, #1     ; B 等级计数加 1

GRADE_NEXT
    ADD R1, R1, #-1    ; 总学生成绩计数减 1
    BRp GRADE_LOOP     ; 若还有成绩,继续遍历

AND R6, R6, #0         
AND R7, R7, #0
LD  R6, A_COUNT
LD  R7, B_COUNT
STR R4, R6, #0     ; 将 A 等级数量存储在 x5100
STR R5, R7, #0     ; 将 B 等级数量存储在 x5101
HALT               ; 停止程序

; 数据段
SOURCE_ADDR  .FILL x4000 ; 成绩源地址
DEST_ADDR    .FILL x5000 ; 排序后来地址
A_COUNT      .FILL x5100 ; A 等级储存地址
B_COUNT      .FILL x5101 ; B 等级储存地址
NUM_15       .FILL #15   ; 共 15 次排序内循环
NUM_16       .FILL #16   ; 总成绩数量
NUM_4        .FILL #4    ; 前25% 数量
NUM_8        .FILL #8    ; 前50% 数量
A_THRESH     .FILL #85   ; A 等级阈值
B_THRESH     .FILL #75   ; B 等级阈值
DEST_END_ADDR .FILL x500F

.END

实验步骤与过程

  1. 准备好数据文件,每次只需加载到Simulator即可,无需手动设置
    在这里插入图片描述
    成绩分别为74,85,60,61,73,84,100,38,66,53,76,82,72,95,74,80
  2. 先把位于从x4000开始的数据,迁移至x5000位置
    在这里插入图片描述
  3. 之后对成绩进行排序,这里采用的是冒泡排序
    在这里插入图片描述
  4. 统计各等级人数,C级无需统计,只需统计A和B等级的学生个数,那么如何统计呢,由于已经把成绩升序排好了,那么只需要倒着遍历即可,从最高的成绩开始,然后维护一个计数器,判断当前成绩是否大于等于85,且计数器的值是否小于等于4(前25%),若这两个条件都符合,就是等级A,等级A数量加一,否则按照类似的方式判断是否是B等级,若是B等级,等级B数量加一。最后将等级A数量存放在x5100,等级B数量存放在x5100处。
    在这里插入图片描述
    在这里插入图片描述
  5. 实验结果
    (1)加载数据和程序:
    在这里插入图片描述
    在这里插入图片描述
    (2)运行前:
    在这里插入图片描述
    在这里插入图片描述
    (3)运行后:
    在这里插入图片描述
    在这里插入图片描述
    (4)验证程序正确性:
    可以看到从x5100开始,成绩从低到高,符合要求:
    在这里插入图片描述
    对成绩降序排序,查看A等级人数和B等级人数:
    在这里插入图片描述
    可以看到有3人获得A,4人获得B,观察向x5100和x5101处的值,正确:
    在这里插入图片描述

实验结论或体会

  1. 在本次实验中,我首次尝试了在LC3利用汇编代码实现一个小程序,熟悉了相关语法和良好的代码分割。认识到了适用标号的诸多好处,如利用LD直接加载数据常量,将地址偏移的计算交给机器负责从而增加代码的可读性;同时也熟悉了关于标号的各种操作。
  2. 另外我熟悉了利用汇编代码编写循环和分支结构的过程,第一次尝试用汇编代码实现冒泡排序。尝试了将一个实际问题通过问题分析,找到相应的算法实现流程及数据结构。
  3. 在本次实验中我也纠正了一些自己的模糊认知。比如标号地址是一个常量,不能做指针移动。其他数据标号也同样是常量,需要将其赋值给寄存器才能进行变量操作。另外lc3仅有8个寄存器,需要合理循环利用寄存器。
  4. 此次实验在找bug上我也花了大量时间,这也提升了我断点调试代码的能力。
  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值