4.1 ISA & 汇编语言
RISC-V:精简指令集
x86:复杂指令集
4.2 调用约定
规定子过程如何获取参数以及如何返回。一般规定:
- 参数、返回值、返回地址
注意:这里RISC-V有相应的整型指令集和浮点型指令集(参考课程视频),可以自行选择需要的部分。寄存器:a0-a7为int参数,f0-f7是float参数 - 将子过程的准备和恢复划分到调用者(caller)和被调用者(callee)
- 没有传到寄存器的参数将以栈的方式传入
- sp栈指针指向第一个没有传入到寄存器的参数
- caller保存的寄存器要在过程调用后恢复该值,调用方需要将这些寄存器压入堆栈或保存到其他位置。callee保存的寄存器会被保存,即A调用B,所有A保存的寄存器在B被调用后可被B重写覆盖。
4.3 Stack
- 栈:高地址到低地址,每个box叫栈帧(stack frame)
- 栈帧最高处是
return address
- sp:stack point,指向栈顶(低地址),保存在寄存器
- fp:frame point,指向栈底(高地址),保存在寄存器,每个栈帧保存父函数的fp(To prev frame)
这个函数调用参考视频讲解(Lecture5 52分钟左右):
sun_then_double
调用sum_to
.global sum_then_double
sum_then_double:
addi sp,sp,-16 # 1
sd ra 0(sp) # 2
call sum_to # 3
li t0,2 # 4
mul a0,a0,t0 # 5
ld ra 0(sp) # 6
addi sp,sp,16
ret
- #1 向下开辟16的空间作为栈帧
- #2 将ra(返回地址)的值存放在sp+0的位置,这里不理解为什么是+0(不应该保存在最高的位置上吗?)
- #3 调用call_to函数,返回值存放在a0
- #4 t0 = 2
- #5 a0*a0
- #6 将之前保存的返回地址 sp+0处加载到ra
- #7 返回caller