前言·
为了更好的完成MIT6.S081的后续实验,花了一点时间学习了RISCV汇编。选择的资源为 伯克利CS61C课程,RISCV的介绍为Lec6到Lec9。本lab为RISCV的练习实验。
有用的资源推荐:
- CS61C 哔哩哔哩搬运
- CS61C-RISCV汇编参考card
- MIT-6.004-RISCV汇编参考card
本lab的要求为: 点这里
实验采用的模拟器为 venus
Exercise 1·
看如下代码,回答问题:
1 | .data |
- What do the .data, .word, .text directives mean (i.e. what do you use them for)? Hint: think about the 4 sections of memory.
- .data 数据段
- .word 定义数据占用一个word(4字节)
- .text 代码段
- Run the program to completion. What number did the program output? What does this number represent?
output: 32 求解斐波那契数列中的第9项是多少
- At what address is n stored in memory? Hint: Look at the contents of the registers.
0x10000010
这里遗留问题:data段的起始位置是由谁决定的?
- Without actually editing the code (i.e. without going into the “Editor” tab), have the program calculate the 13th fib number (0-indexed) by manually modifying the value of a register. You may find it helpful to first step through the code. If you prefer to look at decimal values, change the “Display Settings” option at the bottom.
377 直接修改t3寄存器即可。
Exercise 2: Translating from C to RISC-V·
将如下C代码翻译成RISCV汇编:
1 | int source[] = {3, 1, 4, 1, 5, 9, 0}; |
汇编代码如下:
1 | .data |
- The register representing the variable k.
t0 寄存器
- The register representing the variable sum.
s0 寄存器
- The registers acting as pointers to the source and dest arrays.
- source array pointer: t1
- dest array pointer: t3
- How the pointers are manipulated in the assembly code.
- 指针寻址,需要计算出实际的byte address。 而不像c中类似p操作,自动会计算一个 uint 的大小,如p是int类型指针,p 其实将p移动了4个字节(32位系统)
- 可通过移位操作来完成p++,p–
- 先计算要访问的element的地址,然后通过load或者store指令,加载或保存相应value
Exercise 3: Factorial·
实现阶乘函数,即求解n!
1 | .globl factorial |
Exercise 4: RISC-V function calling with map·
假设有如下结构体定义:
1 | struct node { |
实现map函数,
1 | void map(struct node *head, int (*f)(int)) |
即对每个链表节点都apply一次f函数。
注释给的非常清晰,很好实现。
1 | .globl map |
**这里的考点主要是考虑哪些寄存器需要保存,什么时候保存,是什么时候恢复。**参考lec07即可。
课堂上给出的一个基础结构为:
我们知道riscv中一共有32个寄存器,如下:
其中的Saver列指明了我们在哪里需要保存些什么寄存器,比如 s开头一系列寄存器和sp
需要在callee中保存,而 t开头的寄存器和ra
需要在caller中保存。保持这种 calling convention是非常重要的,能够得到更好的可读的汇编,而不是滥用各类寄存器,到头备受折磨。
总结·
根据CS61C初学了部分汇编,了解了常用指令和伪指令,函数调用过程,call convention以及指令编码格式(虽然这个对本lab来说没什么用)。
之后就重新回归到MIT6.S081了。