address (shown in decimal) 1000 mv a0, s0 # x = a 1004 mv a1, s1 # y = b 1008 addi ra, zero, 1016 # ra = 1016 1012 j sum # jump to sum 1016 ... ... 2000 sum: add a0, a0, a1 2004 jr ra
以上代码为什么使用 jr 而不是 j 是因为 sum 函数可能会在很多地方被调用,我们无法返回到一个固定的位置,所以必须要用 jr 来指定返回的位置。
jump and link(jal)
Single instruction to jump and save return address.
1 2 3 4 5 6
# Before 1008 addi ra, zero, 1016 # ra = 1016 1012 j sum # goto sum
# After 1008 jal sum # ra = 1012, goto sum
1 2
jal rd, Label jump and link jalr
函数调用的一些步骤
1 2 3 4 5 6
intLeaf(int g, int h, int i, int j) { int f; f = (g + h) - (i + j); return f; }
g, h, i, j 分别存储在 a0, a1, a2, a3 f 存储在 s0 我们需要在调用函数之前存储旧的值,由于我们通常没有足够的寄存器来处理每个函数调用,所以将它们存储在内存中的 stack(LIFO)。 Stack 有两个操作: Push: placing data onto stack Pop: removing data from stack
sumSquare: addi sp, sp, -8 # space on stack (push) sw ra, 4(sp) # save ret addr (push) sw a1, 0(sp) # save y (push) mv a1, a0 # mult(x, x) jal mult # call mult lw a1, 0(sp) # restore y (pop) add a0, a0, a1 # mult() + y lw ra, 4(sp) # get ret addr (pop) addi sp, sp, 8 # restore stack (pop) jr ra