L10 RISC-V Procedures

RISCV Function

Six Fundamental Steps in Calling a Function

Pasted image 20241002213228.png

RISC-V Function Call Conventions

Pasted image 20241002213506.png

Instruction Support for Functions

这个图片之前有三个图片,都是介绍图中before的内容,实际上riscv不用before的方式,我们看这个图就好了。
Pasted image 20241002213907.png

关于jal的进一步介绍

Pasted image 20241002214025.png
在RISC-V指令中,rd目标寄存器(destination register) 的缩写,表示指令执行后存储结果的寄存器。例如:

Summary of Instruction Support

Pasted image 20241002214401.png
红框部分解释了 jjrret 是伪指令(pseudoinstructions),即它们并不是 RISC-V 中的原生指令,而是用其他指令组合实现的简化写法。
其中,j 指令其实是用 jal x0, Label 实现的,即:

唯一的

jal是唯一的原生指令

Where Are Old Register Values Saved to Restore Them After Function Call?

Pasted image 20241002220604.png

stack

Pasted image 20241002220622.png

RSICV Function Call Example

Pasted image 20241002220622.png

Example

Pasted image 20241002220816.png

Pasted image 20241002221428.png

Stack Before, During, After Function

Pasted image 20241002221456.png

Nested Calls and Register Conventions

What If a Function Calls a Function? Recursive Function Calls?

好问题,看看DDCA?Lab7manual#todo3
好的我们回到课程。

Pasted image 20241002224816.png

register conventions

Pasted image 20241002224931.png

第一部分(Register Conventions 1/2):

第二部分(Register Conventions 2/2):

RISC-V 函数调用约定将寄存器分为两类,以减少昂贵的寄存器溢出和恢复操作:

  1. 函数调用后保存的寄存器
    • 调用方可以依赖这些寄存器的值不变。
    • 包括堆栈指针(sp)、全局指针(gp)、线程指针(tp)、以及“保存寄存器” s0s11(其中 s0 也称为帧指针 fp)。
  2. 函数调用后不保存的寄存器
    • 调用方不能依赖这些寄存器的值保持不变。
    • 包括参数/返回值寄存器 a0-a7,返回地址寄存器 ra,以及“临时寄存器” t0-t6

关于s0-s11:

“保存寄存器” s0s11(也称为 caller-saved registerssaved registers)在 RISC-V 的函数调用约定中主要用于保存跨函数调用需要保持的值。
具体来说,它们的作用是:

  1. 调用方依赖:调用函数(CalleR)可以依赖这些寄存器的值在被调用函数(CalleE)执行完后保持不变。因此,如果被调用函数需要使用这些寄存器,它必须先将当前值保存(通常保存在栈中),在函数返回前再恢复原值。
  2. 典型用途:这些寄存器通常用于保存全局变量、跨多个函数调用的局部变量、或者一些需要在多个函数中保持不变的值。由于函数执行时可以依赖它们的值不变,因此减少了重复加载或保存数据的开销。
  3. s0/fp 的特殊作用s0 也被用作帧指针(frame pointer),用于跟踪函数调用栈中的帧起始位置,特别是在需要动态栈分配或调试的场景下,帧指针可以帮助管理和访问局部变量、参数等。
    总结起来,s0s11 的主要职责是在跨函数调用期间保存需要保持不变的值,以保证调用方函数的正确执行。

关于t和a:

a0-a7t0-t6 寄存器在 RISC-V 的调用约定中被称为 不保存寄存器(caller-saved registers),即调用方不能依赖它们在函数调用后保持原值。因此: