先来一个计算阶乘的递归过程(C编写):
int fact(int n)
{
if(n<1)
return (1);
else
return (n * fact (n - 1) )
}
参数n对应$a0
上代码
fact:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0, $a0, 1
beq $t0, $zero, L1
--------------------------
addi $v0, $zero, 1
addi $sp, $sp, 8
jr $ra
--------------------------
L1: addi $a0, $a0, -1
jal fact
--------------------------位置2
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
mul $v0, $a0, $v0
jr $ra
假设 n = 3,用计算机的思维去一步步推
首先计算机正在外面执行指令遇到fact的时候是位置1,等用完fact再返回位置1继续执行主代码。
所以先开2个栈,存放ra(位置1)和a0(n=3),接着判断 a0 > 1,3大于1使得t0=0,继而转到L1
fact:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0, $a0, 1
beq $t0, $zero, L1
使a0=3-1=2,再把a0返回给fact,注意此时指令执行发生跳转,需要记录下ra=位置2
L1: addi $a0, $a0, -1
jal fact
回到上面,继续再开2个栈,存放ra(位置2)和a0(n=2),接着判断 a0 > 1,2大于1使得t0=0,继而转到L1
fact:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0, $a0, 1
beq $t0, $zero, L1
使a0=3-1=1,再把a0返回给fact,注意此时指令执行发生跳转,需要记录下ra=位置2
L1: addi $a0, $a0, -1
jal fact
继续再开2个栈,存放ra(位置2)和a0(n=1),接着判断 a0 > 1,结果不于1使得t0=1
fact:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0, $a0, 1
beq $t0, $zero, L1
终于可以顺序执行下去了,把1赋给返回值v0,再把ra(位置2)和a0(n=1)这两栈退了,jr跳转到ra(位置2)
addi $v0, $zero, 1
addi $sp, $sp, 8
jr $ra
从栈中读取并退掉ra(位置2)和a0(n=2)这两栈,接着v0=v0 * a0=1 * 2,又碰到jr指令跳转到刚刚读取的ra(位置2)
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
mul $v0, $a0, $v0
jr $ra
此时栈中只剩存放ra(位置1)和a0(n=3)的栈,从栈中读取并退掉ra(位置1)和a0(n=3)这两栈,接着v0=v0 * a0=1 * 2 * 3,又碰到jr指令跳转到刚刚读取的ra(位置1)
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
mul $v0, $a0, $v0
jr $ra
至此程序执行完成,程序执行又回到外面,得到了v0=123的返回值