1

関数vbsmeにsadという別の関数を呼び出させようとしています...レジスタとリターンアドレスの保存について、次の手順は正しいですか?発信者はレジスタ$t0〜 $ t7を保存することになっていますが、どこでどのように保存すればよいですか?

vbsme: li $v0, 0   # reset $v0 
     li $v1, 0   # reset $v1
     li  $t0, 1   # i(row) = 1 
     li  $t1, 1   # j(col) = 1
     lw  $t2, 0($a0)  # row size
     lw  $t3, 4($a0)  # col size
     mul  $t4, $t2, $t3  # row * col
     li  $t5, 0   # element = 0
    loop:   bgeq  $t5, $t4, exit  # if element >= row * col then exit

     addi $sp, $sp, -16  # create space on the stack pointer
     sw $ra, -12($sp)  # save return address
     sw $s6, -8($sp)  # save return address
     sw $s7, -4($sp)  # save return address
     subi $s7, $t0, 1  # 1st parameter: i-1
     subi $s6, $t1, 1  # 2nd parameter: j-1
     jal  sad   # calculate the sum of absolute difference using the frame starting from row a0 and col a1
     lw $ra, -12($sp)  # restore return address
     lw $s6, -8($sp)  
     lw $s7, -4($sp)
     addi $sp, $sp, 16  # restore stack pointer
     jr $ra
4

2 に答える 2

2

$sx レジスタは、関数呼び出し全体で変更されないことが保証されているため、値が変更される場合にのみ、呼び出し先 (合計関数) がそれらを保存する責任があります。

一方、$tx レジスタは、関数呼び出しで変更されないことが保証されていないため、それらを保存するのは呼び出し元 (vbsme) の責任です。

呼び出し先スタックに $sx を保存する必要があります。

したがって、sum 関数のコーディングを開始するときは、スタック内のスペースを節約する必要があります。n 個のレジスタを節約したい場合は、n*4 を節約します。

スタック内のスペースは、スタックのベースを指す $sp レジスタを減算することによって節約されます。関数コードの前に、その関数のスタックを作成し、必要に応じて、呼び出し元が保存したすべてのレジスタ、リターン アドレス、およびグローバル ポインタ レジスタを保存する必要があります。

sum:
       #stack frame creation. Caller registers saved, 
       # return address and frame pointer

       subu $sp,$sp,36 #Save space in the stack for registers $s0, $s7 + $ra
       sw   $ra,32($sp)
       sw   $s0,0($sp)
       sw   $s1,4($sp)
       #and so on. Note that also you should save the $ra register only if you are
       # going to call another function

       #do something with $sx  

       #stack frame destruction
       #restore $sx and $ra registers
       lw  $ra,32($sp)
       lw  $s0,0($sp)
       lw  $s1,4($sp)
       ...
       lw  $s7,28($sp)

        jr $ra

ちなみに、慣例により、レジスタ $a0、$a3 は、呼び出している関数への引数を保持する必要があります。また、$s0、$s7 レジスタを使用しているため、追加の作業を行う必要があることに注意してください。慣例では、それらを使用しない場合は保存しないでください。そのため、代わりに $tx (一時) レジスタを使用できます。

于 2010-02-19T17:49:49.403 に答える