ICS计算系统概论实验—Lab2-LC3实现斐波那契数列(变型式)

Posted 之墨_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ICS计算系统概论实验—Lab2-LC3实现斐波那契数列(变型式)相关的知识,希望对你有一定的参考价值。

Lab2

Purpose

calculate a variant of the Fibonacci sequence:

condition:

  • p will be stored in x3100, q will be stored in x3101 and N will be stored in
    x3102.
  • job: store F(N) in x3103.
  • R0-R7 are set to zeroes at the beginning, and your program should start at x3000.
  • Your program should start with .ORIG x3000
  • Your program should end with .END
  • Your last instruction should be TRAP x25 (HALT)
  • Capitalized keywords(also labels) are recommended
  • Spaces after commas ( ADD R0, R0, #1 rather than ADD R0,R0,#1 )
  • Decimal constants start with #, hexadecimal with lowercase x
  • Write comments when necessary

several examples:

N N N p p p q q q F ( N ) F(N) F(N)
100 \\text100 100 256 \\text256 256 123 \\text123 123 146 \\text146 146
200 \\text200 200 514 \\text514 514 456  \\text456 456  818 \\text818 818
300 \\text300 300 1024 \\text1024 1024 789  \\text789 789  1219 \\text1219 1219

Principles

Key issues:

如何进行求余运算

指令集中主要能利用的运算操作有 A D D 、 A N D ADD、AND ADDAND,一般的使用 A D D ADD ADD运算求 x % p x\\%p x%p,取余方式为用 x x x反复减 p p p,当 x x x减至负数时再加上一个 p p p得到的结果即为所求的余数,如果使用这个方法求实验要求的斐波那契数,那么就需要 9 9 9个寄存器分别存储 p , q , N , F ( N − 2 ) , F ( N − 1 ) , − p , − q , F ( N − 2 ) % p , F ( N − 1 ) % q p,q,N,F(N-2),F(N-1),-p,-q,F(N-2)\\%p,F(N-1)\\%q p,q,N,F(N2),F(N1),p,q,F(N2)%p,F(N1)%q,显然寄存器数量不支持这个方法
所以需要利用 p = 2 k p=2^k p=2k这个特点,改进求余运算,注意到在二进制求余运算中,如果模为 2 k 2^k 2k那么就可以利用 A N D AND AND进行按位与 2 k − 1 2^k-1 2k1来求余,即例如 11 % 8 = 3 → 1011 & 0111 = 0011 11\\% 8=3\\rightarrow1011\\&0111=0011 11%8=31011&0111=0011,如果使用这个方法求 F ( N − 2 ) % p F(N-2)\\%p F(N2)%p,就不需要额外寄存器再保存 − p 以 及 F ( N − 2 ) -p以及F(N-2) pF(N2),因为:
F ( ( N + 1 ) − 2 ) % p = F ( N − 1 ) % p = F ( N − 1 ) A N D ( p − 1 ) F((N+1)-2)\\%p = F(N-1)\\%p = F(N-1) AND (p-1) F((N+1)2)%p=F(N1)%p=F(N1)AND(p1)
所以上述初始化代码改写为:

.ORIG x3000
LD R0, BASE ;
LDR R1, R0, #0  ;p -> R0
LDR R2, R0, #1  ;q -> R2
LDR R3, R0, #2  ;N -> R4
AND R0, R0, #0  ;0 -> R0
ADD R0, R0, #1  ;F(N-2) = F(0) = 1 -> R0
ADD R4, R0, #0  ;F(N-1) = F(1) = F(0) = 1 -> R4
ADD R1, R1, #-1 ;p-1->R1
NOT R5, R2      ;NOT q -> R5
ADD R5, R5, #1  ;-q -> R5
ADD R3, R3, #-2 ;N-2 -> R3
ADD R6, R4, #0  ;F(N-1)%q = F(1)%q->R6

这样只需要 R 0 − R 6 R0-R6 R0R6 7 7 7个寄存器,在减少了寄存器的数量同时也简化了后续循环中的求余运算。

如何实现递归计算

根据定义,可以得到如下递推关系式:
F ( N + 1 ) = F ( ( N + 1 ) − 2 ) % p + F ( ( N + 1 ) − 1 ) % q F ( ( N + 1 ) − 2 ) % p = F ( N − 1 ) % p = F ( N − 1 ) A N D ( p − 1 ) F ( ( N + 1 ) − 1 ) % q = F ( N ) % q \\left\\ \\beginaligned &F(N+1)=F((N+1)-2)\\%p+F((N+1)-1)\\%q\\\\ &F((N+1)-2)\\%p = F(N-1)\\%p = F(N-1) AND (p-1)\\\\ &F((N+1)-1)\\%q = F(N)\\%q\\\\ \\endaligned \\right. F(N+1)=F((N+1)2)%p+F((N+1)1)%qF((N+1)2)%p=F(N1)%p=F(N1)AND(p1)F((N+1)1)%q=F(N)%q

依照上述关系式,取余需要借助循环实现反复减法操作,由于 N ≥ 2 N\\ge2 N2,所以初始化得到 F ( 0 ) 、 F ( 1 ) F(0)、F(1) F(0)F(1)之后直接相加得到 F ( 2 ) F(2) F(2),在循环体内首先直接输出该值,再判断是否需要继续循环,即是否满足 N − 1 ≥ 0 N-1\\ge0 N10,不满足则应该结束循环,输出结果,满足条件则继续循环,因为 F ( ( N + 1 ) − 2 ) % p F((N+1)-2)\\%p F((N+1)2)%p可以利用按位与运算直接计算出,所以在第一层循环中就可以完成 F ( N ) 、 F ( ( N + 1 ) − 2 ) % p , F ( ( N + 1 ) − 1 ) F(N)、F((N+1)-2)\\%p,F((N+1)-1) F(N)F((N+1)2)%pF((N+1)1)的计算,在第二层循环中完成 F ( ( N + 1 ) − 1 ) % q F((N+1)-1)\\%q F((N+1)1)%q的计算,这样不断的循环就能够实现递归的计算。

Flow chart:

Procedure

初始化:

  1. R1存储p-1
  2. R2存储q
  3. R3存储N
  4. R0存储F(N-2)%p
  5. R4存储F(N-1)
  6. R5存储 -q
  7. R6存储F(N-1)%q
.ORIG x3000
LD R0, BASE ;
LDR R1, R0, #0  ;p -> R1
LDR R2, R0, #1  ;q -> R2
LDR R3, R0, #2  ;N -> R3
AND R0, R0, #0  ;0 -> R0
ADD R0, R0, #1  ;F(N-2) = F(0) = 1 -> R0
ADD R4, R0, #0  ;F(N-1) = F(1) = F(0) = 1 -> R4
ADD R1, R1, #-1 ;p-1->R1
NOT R5, R2      ;NOT q -> R5
ADD R5, R5, #1  ;-q -> R5
ADD R3, R3, #-2 ;N-2 -> R3
ADD R6, R4, #0  ;F(N-1)%q = F(1)%q->R6

处理:

  1. 计算F(N)
  2. 判断循环条件是否成立
  3. 不成立则跳转至存储
  4. 成立则继续计算F((N+1)-2)%p与F((N+1)-1)%q
  5. 无条件跳转至步骤1
MOD ADD R6, R6, R0  ;F(N) = F(N-2)%p + F(N-1)%q -> R6   
    ADD R3, R3, #-1 ;N-1 -> R3
    BRn BREAK       ;if N-1 < 0 then goto break
    AND R0, R4, R1  ;F((N+1)-2)%p = F(N-1)%p = F(N-1) AND (p-1)
    ADD R4, R6, #0  ;F((N+1)-1) -> R4
RE  ADD R6, R6, R5  ;R6-q -> R6 F((N+1)-1)%q = F(N)%q
    BRzp RE         ;if R6-q >= 0 then goto RE
    ADD R6, R6, R2  ;F((N+1)-1)%q = R6 + q -> R6
    BR MOD          ;goto MOD

存储:

  1. 取x3100地址
  2. 存储数据至x3103
  3. HALT终止程序
BREAK LD   R0, BASE     ;x3100->R0
      STR  R6, R0, #3   ;R6->x3103
      TRAP x25          ;finish

Result

Debug:

过程中遇到的主要问题有:输出结果不对!

检查发现循环结构与初始化均没有问题,发现寄存器的使用存在不对,递归过程的部分寄存器应该需要复用,如图,在循环体中,如果我使用一个新的寄存器R7来存储F(N)结果,那么在执行ADD R7,R7,R2后R7存储了F((N+1)-1)%q的值,此时R6还是初始值,所以需要将R7的值赋给R6,否则会导致结果输出不对!但发现R6除第一次初始化后后续不再需要用到初始值,所以可以复用R6,即下图中的R7都用R6代替。

修改后的循环体如下,R6的复用即解决了上述问题,也减少了使用的寄存器数量

Test:

Judge:

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

    .ORIG x3000
    LD R0, BASE ;
    LDR R1, R0, #0  ;p -> R0
    LDR R2, R0, #1  ;q -> R2
    LDR R3, R0, #2  ;N -> R4
    AND R0, R0, #0  ;0 -> R0
    ADD R0, R0, #1  ;F(N-2) = F(0) = 1 -> R0
    ADD R4, R0, #0  ;F(N-1) = F(1) = F(0) = 1 -> R4
    ADD R1, R1, #-1 ;p-1->R1
    NOT R5, R2      ;NOT q -> R5
    ADD R5, R5, #1  ;-q -> R5
    ADD R3, R3, #-2 ;N-2 -> R3
    ADD R6, R4, #0  ;F(N-1)%q = F(1)%q->R6
    
MOD ADD R6, R6, R0  ;F(N) = F(N-2)%p + F(N-1)%q -> R7
    ADD R3, R3, #-1 ;N-1 -> R3
    BRn BREAK       ;if N-1 < 0 then goto break
    AND R0, R4, R1  ;F((N+1)-2)%p = F(N-1)%p = F(N-1) AND (p-1)
    ADD R4, R6, #0  ;F((N+1)-1) -> R4
RE  ADD R6, R6, R5  ;R7-q -> R7 F((N+1)-1)%q = F(N)%q
    BRzp RE         ;if R7-q >= 0 then goto RE
    ADD R6, R6, R2  ;F((N+1)-1)%q = R6 + q -> R6
    BR MOD          ;goto MOD
    
BREAK LD   R0, BASE     ;x3100->R0
      STR  R6, R0, #3   ;R6->x3103
      TRAP x25          ;finish

BASE .FILL x3100;
     .END

评测结果如下,正常运行,输出正确。

Efficiency of loop structure

在循环体中,F((N+1)-2)%p的计算是在第一层循环中直接通过按位与计算出来的,即计算它的余数只需要一条指令即可,如果采用和F((N+1)-1)%q同样的计算方法:嵌套一个循环,利用ADD运算计算余数,那么需要的指令数与寄存器数量都会更多,循环的效率更低,并且复用了几个寄存器R0、R4、R6,使得过程中用到的寄存器数量更少

以上是关于ICS计算系统概论实验—Lab2-LC3实现斐波那契数列(变型式)的主要内容,如果未能解决你的问题,请参考以下文章

ICS计算系统概论LC3汇编实验Lab5—中断递归解决汉诺塔问题

ICS计算系统概论LC3汇编实验Lab5—中断递归解决汉诺塔问题

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

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

算法实验课-1:斐波那契数列

禅与计算机程序设计艺术使用 16 门编程语言实现斐波那契数列:循环控制指令与函数递归思想