前面讲了x10-x17,一共8个寄存器用于存储变量。而如果超过了8个,就需要用到“栈”(stack)这个概念了:
stack A data structure for spilling registers organized as a last-in�first-out queue.
对于“栈”(stack),几个相关的概念是:
stack pointer A value denoting the most recently allocated address in a stack that shows where registers should be spilled or where old register values can be found. In RISC-V, it is register sp, or x2.
push Add element to stack.
pop Remove element from stack.
当你进行压栈(push)的时候,栈是变大还是变小呢?
By historical precedent, stacks “grow” from higher addresses to lower addresses.
好像真的在“压”,所以从大到小了。
示例:
答案:
The parameter variables g, h, i, and j correspond to the argument registers x10, x11, x12, and x13, and f corresponds to x20.
首先,定义label:
leaf_example:
随后,压栈并存储:
addi sp, sp, -24 // adjust stack to make room for 3 items
sd x5, 16(sp) // save register x5 for use afterwards
sd x6, 8(sp) // save register x6 for use afterwards
sd x20, 0(sp) // save register x20 for use afterwards
然后是进行相应的运算,实现C代码:
add x5, x10, x11 // register x5 contains g + h
add x6, x12, x13 // register x6 contains i + j
sub x20, x5, x6 // f = x5 − x6, which is (g + h) − (i + j)
再得到f的数值:
addi x10, x20, 0 // returns f (x10 = x20 + 0)
最后是弹栈:
ld x20, 0(sp) // restore register x20 for caller
ld x6, 8(sp) // restore register x6 for caller
ld x5, 16(sp) // restore register x5 for caller
addi sp, sp, 24 // adjust stack to delete 3 items
并返回:
jalr x0, 0(x1) // branch back to calling routine
对应的图示:
RISC-V将寄存器分成了两组:
x5−x7 and x28−x31: temporary registers that are not preserved by the callee (called procedure) on a procedure call n
x8−x9 and x18−x27: saved registers that must be preserved on a procedure call (if used, the callee saves and restores them)
网友评论