再帰関数を書いてみよう

    .text
.globl fact
.ent fact
fact:
subu $sp, 32 # $sp(スタックポインタ)-32を$spに代入。スタックフレームを32バイト確保ってこと
sw $31, 28($sp) # $31(戻り先アドレス)を$sp+28が示すメモリ(確保したスタックフレームの一個目)に退避。store word

move $8, $4

bne $8, $0, callrec # $8と$0の内容が違ったら(not equal)callrecに飛ぶ(branch)
addu $2, $0, 1 # $2(戻り値)に1を代入

addu $sp, 32 # $sp+32を$spに代入。スタックフレーム32バイトを開放
j $31 # $31(戻り先アドレス)にjump

callrec:
subu $4, $8, 1 # $8-1を$4に代入
sw $8, 24($sp) # $8を$sp+24(スタックフレームの二個目)に退避
jal fact # (たぶん)$31にこれの次の命令のアドレスを入れて、factに飛ぶ
lw $8, 24($sp) # $8に$sp+24(スタックフレームの二個目)の値を戻す。load word
mul $2, $2, $8 # $2(戻り値)に$2(factが返してきた戻り値)*8を代入

lw $31, 28($sp) # $31に$sp+28が示すメモリ(確保したスタックフレームの一個目)の値を復帰
addu $sp, 32 # $sp=$sp+32。スタックフレームの開放
j $31 # $31にjump
.end fact

とりあえず動いた。要求が簡単だからこっちの方が長くなる。Cなら
int fact(int x){
if(x == 0) return 1;
return x*fact(x - 1);
}
で済むのにね。これってfact(0)したらひどいことになるね。
書き直した。
なんとなく適当なコメントをつけてみた。

test