1

だから私は(一般的に)階乗を計算するこのコードを持っていますが、この例では10の階乗を計算します

    .data 0x10008000
    .word 10
    .word 1
    .word 0
    .ascii "The factorial of 10 is %d \n"
    .text
    .globl main
main:
    addi $sp, $sp, -32
    sw $ra, 20($sp)
    sw $fp, 16($sp)
    addiu $fp, $sp,28
    lw $a0, 0($gp)
    jal fact

    ...

    lw $ra, 20($sp)
    lw $fp, 16($sp)
    addiu $sp, $sp, 32
    jr $ra
fact:
    addiu $sp, $sp, -32
    sw $ra, 20($sp)
    sw $fp, 16($sp)
    addiu $fp, $sp, 28
    sw $a0, 0($fp)
    lw $v0, 0($fp)      
    lw $t0, 4($gp)
    slt $t1,$v0,$t0     
    bne $t0, $t1, L2    
    addi $v0, $v0, 1
    jr L1
 L2:
    lw $v1, 0($fp)
    addi $v0, $v1, -1
    sw $v0, 8($gp)
    lw $a0, 8($gp)
    jal fact                   
    lw $v1, 0($fp)      
    mul $v0, $v0, $v1    
 L1:
    lw $ra, 20($sp)
    lw $fp, 16($sp)
    addiu $sp, $sp, 32
    jr $ra

私の問題は、これは L2 での乗算の後に jr L1 コマンドを必要としないということですか? 再帰はどのように機能しますか? 以前の数値を保存する方法は必要ありませんか? これはスタックの仕事だと思いますが、関数が呼び出されるたびに、以前に保存された変数が上書きされるように思えます。

PS誰かが私の問題を理解したかどうかわかりません。下手な英語で申し訳ありません...

4

2 に答える 2

0

再帰には「手動スタック管理」の導入が必要であり、これを実装するには明らかに労力がかかります。さまざまな理由から、すべてのコンパイラがサポートしているわけではありません

それはすべて、異なるパラメータ ツリー間で拡張および縮小するスタック上で発生し、観察するのは非常に驚くべきことです。

「そのことについて学びたい」場合は、非常に再帰的な現実世界の問題である「ハノイの塔」について調査することをお勧めします

ここに素敵な説明があります

http://www.cs.cmu.edu/~cburch/survey/recurse/hanoiimpl.html

再帰を理解すると、数独ソルバーなどの非常に複雑な問題に使用できます

典型的な数独には、約 20 から 30 の異なるシナリオがあります

したがって、「不可能な」sudoko に対しても魔法のように機能する単一の再帰的ソリューションを作成することで、20 以上の手動シナリオのプログラミングを回避できます。

于 2013-05-12T23:43:20.760 に答える