一生一芯F4

1
2
3
4
5
6
7
8
0: li r0, 10   # 这里是十进制的10
1: li r1, 0
2: li r2, 0
3: li r3, 1
4: add r1, r1, r3
5: add r2, r2, r1
6: bner0 r1, 4
7: bner0 r3, 7

继续执行上述的指令

题目

我们用(PC, r0, r1, r2, r3)的格式来记录寄存器的值

1
2
3
4
5
6
7
8
9
10
11
>PC r0 r1 r2 r3
>(0, 0, 0, 0, 0) # 初始状态
>(1, 10, 0, 0, 0) # 执行PC为0的指令后, r0更新为10, PC更新为下一条指令的位置
>(2, 10, 0, 0, 0) # 执行PC为1的指令后, r1更新为0, PC更新为下一条指令的位置
>(3, 10, 0, 0, 0) # 执行PC为2的指令后, r2更新为0, PC更新为下一条指令的位置
>(4, 10, 0, 0, 1) # 执行PC为3的指令后, r3更新为1, PC更新为下一条指令的位置
>(5, 10, 1, 0, 1) # 执行PC为4的指令后, r1更新为r1+r3, PC更新为下一条指令的位置
>(6, 10, 1, 1, 1) # 执行PC为5的指令后, r2更新为r2+r1, PC更新为下一条指令的位置
>(4, 10, 1, 1, 1) # 执行PC为6的指令后, 因r1不等于r0, 故PC更新为4
>(5, 10, 2, 1, 1) # 执行PC为4的指令后, r1更新为r1+r3, PC更新为下一条指令的位置
>......

尝试继续执行指令, 记录寄存器的状态变化过程. 你现执行到最后时, 处理器处于什么样的状态? 上述数列的求和结果在哪个寄存器中?

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
(6, 10, 2, 3, 1)
(4, 10, 2, 3, 1)
(5, 10, 3, 3, 1)
(6, 10, 3, 6, 1)
(4, 10, 3, 6, 1)
(5, 10, 4, 6, 1)
(6, 10, 4, 10, 1)
(4, 10, 4, 10, 1)
(5, 10, 5, 10, 1)
(6, 10, 5, 15, 1)
(4, 10, 5, 10, 1)
(5, 10, 6, 10, 1)
(6, 10, 6, 21, 1)
(4, 10, 6, 21, 1)
(5, 10, 7, 21, 1)
(6, 10, 7, 28, 1)
(4, 10, 7, 28, 1)
(5, 10, 8, 28, 1)
(6, 10, 8, 36, 1)
(4, 10, 8, 36, 1)
(5, 10, 9, 36, 1)
(6, 10, 9, 45, 1)
(4, 10, 9, 45, 1)
(5, 10, 10, 45, 1)
(6, 10, 10, 55, 1)
(7, 10, 10, 55, 1) # 执行PC为6的指令后, 因r1等于r0, 故PC更新为7
(7, 10, 10, 55, 1) # 执行PC为7的指令后, 因r3不等于r0, 故PC更新为7
# 此后在7循环

计算10以内的奇数之和

题目

尝试用上述指令编写一个程序, 求出10以内的奇数之和, 即计算1+3+5+7+9. 编写后, 尝试列出处理器状态的变化过程, 以此来检查你编写的程序是否正确.

程序如下:

1
2
3
4
5
6
7
8
9
0: li r0, 9
1: li r1, 1
2: li r2, 0
3: li r3, 2
4: add r2, r2, r1
5: add r1, r1, r3
6: add r2, r2, r1
7: bner0 r1, 5
8: bner0 r3, 8

过程如下:

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
(0, 0, 0, 0, 0)
(1, 9, 0, 0, 0)
(2, 9, 1, 0, 0)
(3, 9, 1, 0, 0)
(4, 9, 1, 0, 2)
(5, 9, 1, 1, 2)
(6, 9, 3, 1, 2)
(7, 9, 3, 4, 2)
(5, 9, 3, 4, 2)
(6, 9, 5, 4, 2)
(7, 9, 5, 9, 2)
(5, 9, 5, 9, 2)
(6, 9, 7, 9, 2)
(7, 9, 7, 16, 2)
(5, 9, 7, 16, 2)
(6, 9, 9, 16, 2)
(7, 9, 9, 25, 2)
(8, 9, 9, 25, 2) #之后在此循环
```

## 继续执行上述程序

```C
#include <stdio.h>

/* 1 */ int main() {
/* 2 */ int sum = 0;
/* 3 */ int i = 1;
/* 4 */ do {
/* 5 */ sum = sum + i;
/* 6 */ i = i + 1;
/* 7 */ } while (i <= 10);
/* 8 */ printf("sum = %d\n", sum);
/* 9 */ return 0;
/* 10*/ }
```

```State Machine
PC sum i
(2, ?, ?) # 初始状态
(3, 0, ?) # 执行PC为2的语句后, sum更新为0, PC更新为下一条语句的位置
(5, 0, 1) # 执行PC为3的语句后, i更新为1, PC更新为下一条语句的位置(第4行无有效操作, 跳过)
(6, 1, 1) # 执行PC为5的语句后, sum更新为sum + i, PC更新为下一条语句的位置
(7, 1, 2) # 执行PC为6的语句后, i更新为i + 1, PC更新为下一条语句的位置
(5, 1, 2) # 执行PC为7的语句后, 由于循环条件i <= 10成立, 因此重新进入循环体
......
题目

尝试继续执行上述代码, 记录状态的变化过程. 程序执行结束时, 程序处于什么样的状态?

Machine
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
(6, 3, 2)
(7, 3, 3)
(5, 3, 3)
(6, 6, 3)
(7, 6, 4)
(5, 6, 4)
(6, 10, 4)
(7, 10, 5)
(5, 10, 5)
(6, 15, 5)
(7, 15, 6)
(5, 15, 6)
(6, 21, 6)
(7, 21, 7)
(5, 21, 7)
(6, 28, 7)
(7, 28, 8)
(5, 28, 8)
(6, 36, 8)
(7, 36, 9)
(5, 45, 9)
(6, 45, 9)
(7, 45, 10)
(5, 45, 10)
(6, 55, 10)
(7, 55, 11)
(8, 55, 11) # 执行PC为7的语句后, 由于循环条件i <= 10不成立, 因此跳出循环体
(9, 55, 11)
(10, 55, 11)

从状态机视角理解数列求和电路的工作过程

题目

在上一小节中, 你已经通过寄存器和加法器搭建出一个简单数列求和电路, 用于计算1+2+...+10. 尝试列出电路状态的变化过程.

假设左侧的寄存器为A,右侧的寄存器为B

数列求和.png

A   B
(0, 0) #初始状态
(1, 0) 
(2, 1)
(3, 3)
(4, 6)
(5, 10)
(6, 15)
(7, 21)
(8, 28)
(9, 36)
(10, 45)
(11, 55)
(11, 55) #往后保持在(11, 55)的状态