0

私はCでこの関数を持っています:

int func(int n0, int n){
    if (n > 1){
        int nFinal = func(n0, --n);
        return (nFinal*nFinal) + n0;
    }
    return n0;
}

そしてそれをアセンブリでプログラムしたい。私はこのコードを持っています:

    .data
    .text
    .globl  func
func:
    addi            $29,$29, -4
    sw      $ra,0($29)
    move            $8,$4       
    move            $9,$5       
    ble     $9,1,fim
    sub     $9,$9,1
    move            $5,$9
    jal     func
    move            $4,$11
    jal     quadrado
    add     $11,$2,$8
    j       fim
quadrado:
    mul     $2,$4,$4
    jr      $31
fim:    
    lw      $31,0($29)  
    move            $2,$11
    jr      $31

ble$4と$5で渡されたパラメーターがそれぞれ2と1である場合、プログラムが期待どおりに機能する命令に到達したことがわかります。ラベルにジャンプしfim、スタックから戻りアドレスを復元して、戻り値をmain関数に渡します。

問題は、パラメーター$5の値が未定義であるということです。任意の値にすることができます。そして、私のプログラムの問題は、私のmain関数からのリターンアドレスが失われ、プログラムがそれに戻ることができないことだと思います。wenプログラムが命令に到達しjal func、リターンアドレスが命令のmainリターンアドレスに置き換えられたと思いjal funcます。

どうすればこの問題を解決できますか?(コードを尋ねるのではなく、いくつかの指示だけを求めます)

4

2 に答える 2

1

[...]そして、私のプログラムの問題は、私のmain関数からのリターンアドレスが失われ、プログラムがそれに戻ることができないことだと思います。wenプログラムが命令に到達しjal func、リターンアドレスが命令のmainリターンアドレスに置き換えられたと思いjal funcます。

かなり。$29関数の開始時にスタックポインター( / )をデクリメントして、リターンアドレス( / )$spを保存するスペースを作成していますが、最後にリターンアドレスをリロードした後、スタックポインターの対応する増分が欠落しています- -値を見ていますが、実際にはスタックからポップしていません。$31$ra

于 2012-04-15T19:13:27.597 に答える
1

コードにコメントを付けると、非常に役立ちます。一時レジスターを使用すると、おそらくさらに複雑になります。一時レジスターを 1 つだけ使用する必要があります。funcここで、日常生活に少し役立ちます。残りはコンプリートできると思います。また、戻りアドレスをポップするときは、スタック ポインターを移動することを忘れないでください。

func:
        #push rtn. addr. onto stk
        sw $ra, 0($sp)
        subi $sp, $sp, 4

        #result = arg0
        move $t0, $a0

        #if arg1 <= 1 return arg0           
        ble $a1, 1, rtn

        #call func(arg0, arg1-1)
        subi $a1, $a1, 1
        jal func

        #result = func(arg0, arg1-1)^2 + arg0
        mul $t0, $v0, $v0
        add $t0, $t0, $a0

rtn:
于 2012-04-15T22:25:17.223 に答える