RISC-V
CS61C-RISC-V
这一部分主要讲了RISC-V指令,包括引入,格式(尤其是Calling Convention),原理以及几种不同的指令类型
一个很重要的参考:命令参考附录
Intro
我们知道高级编程语言是不能被计算机直接看懂的,计算机明白的是机器语言,即二进制码,而人类使用的编程语言,离机器语言中间还有个中间体——即汇编语言(Assembly Language)
如下图所示,我们目前探索的计算机抽象层级即位于第二层次:
汇编语言有很多种,在61C里我们使用的是经典版本——RISC-V,由于现在的电脑不能直接运行之,所以需要在Venus平台上运行,这是课程已经为我们提供好了的
RISC-V
寄存器(Register)
- 仅次于CPU的存储单元!
- 非常快!
- 每个寄存器存储32或64bits的数据
- 一共32个,编号从x0-x31
这是我们的RISC-V语言直接操纵的对象!
基本特点与命令格式
不同于高级语言,RISC-V没有所谓的数据类型
一切操作都是针对寄存器(里的数据)!!!
命令格式也十分统一,如下图所示,实际情况中也只有很少不同:
- 命令总体包括数学运算,逻辑控制,内存控制等部分,详情可参考命令参考附录
Calling Convention
最重要的一集(雾)
显然,如果在所有的RISC-V汇编程序里都使用x0-x31这样的寄存器命名,无疑和C语言里变量命名全部abcdefg一样难以理解。
由此,我们引申出汇编语言里的”Coding Style”,也即Calling Convention,通过一些约定俗成的规定来规范与优化我们的代码格式
Terminology
- Callee:被Call的函数
- Caller:去Call别的函数的函数
一个函数既可以是caller也可以是callee,这一点我尤其建议在Lab 4里的练习里加深体会,因为那里的练习使用了递归函数,更加形象的说明了这个特点
来者不善!
你才是来者!
Callee-saved Registers
指在一个函数被调用前后内容保持不变的寄存器
从名字上来理解,即“需要由被调用者主动保存的寄存器”
- 包括s0-s11
- 一个特殊的寄存器:sp(x2),用来指示栈下端的地址位置
那么如何来保存/读取寄存器内容呢——使用sp,sw,lw三件套,调节栈指针的同时,进行数据的存取
从Coller的视角看:调用函数前后,这些寄存器的值不变
Caller-saved Registers
- ra:负责存储地址,在jumping时生效
- a0-a7:给函数传参
- t0-t6:暂时使用的寄存器,可理解为临时变量
理解上同理,只是由调用者保存,参考下图:
一般的储存原则
- ra必存
- callee类型的,只要用了就存
- caller类型的,只有前后都用了才存
- 有存必有取,否则会造成地址紊乱
指令类型
一共六种:R,I,S,U,B,J,简记一下即可,附录里都有
不同类型的指令对应的二进制码构成不同,执行的指令类型也不同(这似乎是UCB考试喜欢考的?)