为什么$ ra呼叫者被保存在RISC-V中

时间:2020-01-11 09:52:51

标签: assembly riscv

我发现在RISC-V中,ra是保存呼叫者的,在MIPS中,ra是被呼叫者的,这意味着在RISC-V中,被呼叫者可以直接更改ra中的值而无需保存,但是由于ra已更改,被叫方如何返回给呼叫方?

2 个答案:

答案 0 :(得分:3)

RISC V ra和MIPS $ ra的用法实际上是相同的,无论其名称如何。

由于调用者(需要返回其调用者)和(非叶子)被调用者都需要重新设置返回地址寄存器的用途,因此该寄存器中的值需要保留。唯一符合逻辑的方法是,如进入s / $ s一样保留被调用者保存的寄存器,则在进入时保留一次寄存器,并在退出时恢复一次寄存器。

但是,一旦保存起来,函数就可以将返回地址寄存器重新用于其他用途,并且任何此类用法都将遵循调用者保存约定(不同于$ s寄存器,保证在整个调用过程中都将其保留)。

因此,有效地,ra / $ ra可以在不同时间表现为被叫方保存和呼叫方保存。

在函数调用后,调用者无法依赖放置在ra / $ ra中的值(就像使用$ s寄存器一样),因此调用者可以保存。但是,当被呼叫者保留ra / $ ra时,它会像保存$ s被呼叫者-保存寄存器一样保留它,即在序言/结尾中。

相反,$ t寄存器如果被调用方保留以便在函数调用中保留下来,则必须在每次更新该值后保留(例如在第一次初始化后最少),这就是调用方保存行为。这些寄存器首先被初始化,然后被保留,而$ s寄存器被首先保留,然后被初始化。

ra / $ ra具有被调用者和调用者保存的行为:它需要在初始化和重用/重新使用之前被保存,这是一种被调用者保存的方法,但是,放入$ ra的变量不能在函数调用中保留下来,因此要在函数调用中幸存下来,就需要初始化然后保存。

答案 1 :(得分:2)

我发现在RISC-V中,ra被呼叫者保存了

ra是保存在调用方中的寄存器这一事实意味着,在控制流返回到调用方时,调用方无法假定其值已保留。因此,如果调用方想要保留ra,则必须在将控件转移给被调用方之前保存ra

可以通过jaljalr来将控制权转移到子例程。它们都将以下指令的地址-返回地址-装入目标寄存器(通常为ra)。因此,在一般情况下:

  • ra在调用子例程时被破坏。
  • ra包含返回到当前子例程的调用者的返回地址。

第一点意味着两次调用之间未保留寄存器ra。因此,如果子例程要维护ra –调用方子例程的返回地址–调用子例程时,必须在执行调用之前保存ra

在RISC-V中,被叫方可以直接更改ra中的值而无需保存,但是由于ra已更改,被叫方如何返回给呼叫方?

如果被叫方丢失了给其呼叫者的回信地址,则无法返回给呼叫者。这就是为什么ra必须在通话前保存的原因,因为它在执行通话时会阻塞。