ICS计算系统概论LC3汇编实验Lab4—排序和计数 Sort and Count

Lab4 Sort and Count

Purpose

完成"排序和计数"
有 16 个学生的分数。如果学生得分在85分或以上,并且进入前25%,他/她将获得A。 如果他/她没有得到A,但得分75或以上,并且处于前50%,他/她将获得B。 注意:每个分数都存储在从地址 x4000 开始的连续内存位置中。 每个分数都是介于 0 和 100 之间的整数。 每个人都得到不同的分数。

condition:

  1. 程序应按升序(从小到大)对分数进行排序,并将它们存储在从地址 x5000 开始的连续内存位置。
  2. 程序应计算有多少学生获得 A 并将数字存储在 x5100 中。
  3. 程序应计算有多少学生获得 B 并将数字存储在 x5101 中。
  4. R0-R7 在开头设置为零,程序应从 x3000 开始。

Principles

Key issues:

怎么计数A和B的个数

根据题意,A和B只来自于分数前8名,所以我们可以在对数组排序后统计前8名中大于等于75和大于等于85分的个数,并且显然大于等于75的个数一定>=大于等于85分的个数,因此就可以分为两种情况:

  1. 当大于等于85分的个数大于等于4个:A的个数为4,B的个数就是大于等于75分的个数减4
  2. 当大于等于85分的少于4个:可以分为两种情况:
    1. 大于等于75分的和大于等于85分的一样多,此时A的个数就是大于等于85分的个数,而B的个数为0
    2. 大于等于75分的比大于等于85分的更多,此时A的个数就是大于等于85分的个数,而B的个数为大于等于75分的个数减去大于等于85分的个数

怎么排序数组

联想到高级语言编程时用到的许多种排序方法,冒泡排序、选择排序等,其中冒泡排序最简单,所以选择实现冒泡排序,由于排序结果要存储在x5000开始的内存中,所以排序前可以先将数据从x4000存至x5000中,再进行排序

Procedure

        AND R1, R1, #0    ; >=75分的人
        AND R2, R2, #0    ; >=85分的人
        AND R5, R5, #0;
        ADD R5, R5, #8   ; counter
        LD R3, NEWADDR
        ADD R3, R3, #15   ; x500F   
SCORE   ADD R5, R5, #-1
        BRn COMP;
        LDR R6, R3, #0  ;取数x
        ADD R3, R3, #-1;
        LD R4, NOT_75    ; 取-75
        ADD R7, R6, R4;  x-75
        BRzp JUGA        ;x>=75
        BR  SCORE;
JUGA    ADD R1, R1, #1;     >=75的人+1
        LD R4, NOT_85;      取-85
        ADD R7,R6, R4; x-85 
        BRzp CNTA   ;x>=85
        BR SCORE    ;
CNTA    ADD R2, R2, #1;     >=85的人+1
        BR SCORE;
COMP    ADD R3, R2, #-4; 前50%中85分>=4个
        BRzp CONI         ;                
        BR CONII        ;85少于4个
CONI    AND R2, R2, #0; 
        ADD R2, R2, #4; 4个A
        ADD R1, R1, #-4; B的个数就是大于75的-4
        BR OUTPUT;
CONII   NOT R4, R2      ;
        ADD R4, R4, #1;
        ADD R3, R4, R1; >=75个数-85个数
        BRz CONIII      ;  >=75的个数和85一样
        AND R1, R1, #0;
        ADD R1, R3, R1;
        BR OUTPUT;
CONIII  AND R1, R1, #0;          
        BR OUTPUT;

以上程序段实现了统计A和B的个数,只对从x500F开始往下的8个数统计,首先统计8个数中,大于等于85分的个数和大于等于75分的个数,得到这两个数后,并且大于等于75的个数必然比85的更多或者至少一样多,所以可以分成两种情况来分析,分别是>=85分的人数>=4个以及>=85分的人数<4个,这里第二种情况可以分成两种情况:>=75的个数和85一样以及>=75的个数比85的更多

SORT    ST R7, SAVE
        LD R3, OLDADDR  ; 
        LD R4, NEWADDR ; 
        LD R1, NOT_15  ; -15

INIT    ADD R7, R0, R1       
        BRp STAR
        LDR R2, R3, #0;
        STR R2, R4, #0
        ADD R0, R0, #1
        ADD R3, R3, #1
        ADD R4, R4, #1
        BRnzp INIT
            
STAR  LD R0, IS_15
FORI  ADD R0, R0, #-1  ; for i
      BRn BREAK
      NOT R3, R0
      ADD R3, R3, #1   
      AND R2, R2, #0   
      AND R1, R1, #0   
      LD R4, NEWADDR 

FORJ  ADD R7, R1, R3
      BRp JUDGE
      ADD R1, R1, #1
      LDR R5, R4, #0   ; j
      ADD R4, R4, #1
      LDR R6, R4, #0   ; j+1
      NOT R6, R6
      ADD R6, R6, #1
      ADD R7, R5, R6
      BRnz FORJ
      LDR R6, R4, #0
      STR R5, R4, #0
      STR R6, R4, #-1
      ADD R2, R2, #1
      BRnzp FORJ

JUDGE ADD R2, R2, #0
      BRz BREAK
      BRnzp FORI

BREAK  LD R7, SAVE
      RET

如上是使用的排序的程序段,
将其作为一个函数,程序开始时使用JSR调用它将数据排序好之后再统计AB个数,需要注意的是LC3默认将R7寄存器用来存储程序返回地址,并且函数体会改变R7内容,因此我们要将R7的内容先Save,程序结束时再恢复,否则函数结束不能正确返回。

Result

Debug:

过程中遇到的主要问题就是:上述的函数返回的问题,最开始没有意识到RET的地址默认是存储在中R7的,所以导致程序不能正常运行

Test:
解决方案就是申请一块内存作为SAVE存储R7内容,在函数开头将R7内容存入SAVE,结束时再取出SAVE存入R7,这样函数结束时就能返回到正确位置了

SAVE .BLKW #1
ST R7, SAVE
LD R7, SAVE

Judge:

在本地 LC3Tool \text{LC3Tool} LC3Tool调试完毕后,将代码整理如下:用于网站在线 lc3 \text{lc3} lc3评测

            .ORIG x3000
            JSR SORT
            
        AND R1, R1, #0    ; >=75分的人
        AND R2, R2, #0    ; >=85分的人
        AND R5, R5, #0;
        ADD R5, R5, #8   ; counter
        LD R3, NEWADDR
        ADD R3, R3, #15   ; x500F   
SCORE   ADD R5, R5, #-1
        BRn COMP;
        LDR R6, R3, #0  ;取数x
        ADD R3, R3, #-1;
        LD R4, NOT_75    ; 取-75
        ADD R7, R6, R4;  x-75
        BRzp JUGA        ;x>=75
        BR  SCORE;
JUGA    ADD R1, R1, #1;     >=75的人+1
        LD R4, NOT_85;      取-85
        ADD R7,R6, R4; x-85 
        BRzp CNTA   ;x>=85
        BR SCORE    ;
CNTA    ADD R2, R2, #1;     >=85的人+1
        BR SCORE;
COMP    ADD R3, R2, #-4; 前50%中85分>=4个
        BRzp CONI         ;                
        BR CONII        ;85少于4个
CONI    AND R2, R2, #0; 
        ADD R2, R2, #4; 4个A
        ADD R1, R1, #-4; B的个数就是大于75的-4
        BR OUTPUT;
CONII   NOT R4, R2      ;
        ADD R4, R4, #1;
        ADD R3, R4, R1; >=75个数-85个数
        BRz CONIII      ;  >=75的个数和85一样
        AND R1, R1, #0;
        ADD R1, R3, R1;
        BR OUTPUT;
CONIII  AND R1, R1, #0;          
        BR OUTPUT;

OUTPUT  LD R3, RESULT
        STR R2, R3, #0
        STR R1, R3, #1
        HALT

;冒泡排序
SORT    ST R7, SAVE
        LD R3, OLDADDR  ; 
        LD R4, NEWADDR ; 
        LD R1, NOT_15  ; -15

INIT    ADD R7, R0, R1       
        BRp STAR
        LDR R2, R3, #0;
        STR R2, R4, #0
        ADD R0, R0, #1
        ADD R3, R3, #1
        ADD R4, R4, #1
        BRnzp INIT
            
STAR  LD R0, IS_15
FORI  ADD R0, R0, #-1  ; for i
      BRn BREAK
      NOT R3, R0
      ADD R3, R3, #1   
      AND R2, R2, #0   
      AND R1, R1, #0   
      LD R4, NEWADDR 

FORJ  ADD R7, R1, R3
      BRp JUDGE
      ADD R1, R1, #1
      LDR R5, R4, #0   ; j
      ADD R4, R4, #1
      LDR R6, R4, #0   ; j+1
      NOT R6, R6
      ADD R6, R6, #1
      ADD R7, R5, R6
      BRnz FORJ
      LDR R6, R4, #0
      STR R5, R4, #0
      STR R6, R4, #-1
      ADD R2, R2, #1
      BRnzp FORJ

JUDGE ADD R2, R2, #0
      BRz BREAK
      BRnzp FORI

BREAK  LD R7, SAVE
      RET

SAVE .BLKW #1
IS_15 .FILL x000F
NOT_15 .FILL xFFF1 ;-15
NOT_75 .FILL xFFB5 ; -75
NOT_85 .FILL xFFAB ; -85
OLDADDR .FILL	x4000
NEWADDR .FILL x5000
RESULT .FILL	x5100

           .END

评测结果如下,正常运行,输出正确。
这里是引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之墨_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值