在发出环境调用之前是否应该保存临时寄存器?

Should temporary registers be saved before issuing an environment call?

在下面的 RISC-V 汇编代码中:

...
#Using some temporary (t) registers
...

addi a7,zero,1 #Printint system call code
addi a0,zero,100
ecall

...

在使用ecall之前是否应该将任何临时(t)寄存器保存到堆栈中?当使用 ecall 时,会发生异常,内核模式打开并且代码从异常处理程序中执行。有些信息是在异常发生时保存的,比如 EPCCAUSE ,但是临时寄存器呢?出于安全原因,环境调用被认为不像过程,但它们看起来像。过程调用约定在这种情况下是否仍然适用?

你是正确的,硬件捕获了一些信息,例如 epc(如果没有,中断的 pc 将在控制转移到异常处理程序的过程中丢失)。

然而,这就是硬件所做的一切——剩下的就是软件了。此处,RARS 为 ecall.

提供异常处理程序

RARS 文档状态(来自系统调用的帮助部分,这就是 MIPS 上的调用(RARS 来自 MARS)):

Register contents are not affected by a system call, except for result registers as specified in the table below.

在帮助中的这句话下面是 ecall 函数代码 table 标记为“Table of Available Services”,其中 1 是 PrintInt.

Should any temporary (t) registers be saved to the stack before using ecall?

不,没有必要,$t 寄存器不受 ecall 的影响。

这也意味着我们可以添加 ecalls 来进行 printf 风格的调试,而不用担心保留 $t 寄存器,这很好。但是,请记住这一点,我们通常可能会避免将 $a0 和 $a7 作为我们自己的变量,因为放入 ecall 进行调试将需要这些寄存器。


此外,您可以编写自己的异常处理程序,它不必遵循任何特定的参数传递甚至寄存器保存约定。