1. ホーム
  2. assembly

[解決済み] MIPS: スタックポインタ($sp)とスタックの関連した使用法

2022-02-04 16:39:03

質問

現在、コンピュータ組織の中間試験に向けて勉強していますが、スタックポインタとスタックを完全に理解しようとしています。私はこの概念にまつわる次のような事実を知っています。

  • 先入れ先出しの原則に従う
  • そして、スタックに何かを追加するには、2段階のプロセスが必要です。

    addi $sp, $sp, -4
    sw $s0, 0($sp)
    
    

私が思うに、私が完全に理解するのを止めているのは、スタックポインタでデータを追跡する必要がある、またはしたい、関連する自明な状況を思いつくことができないからです。

どなたか、全体的なコンセプトを詳しく説明し、有用なコード例を教えていただけませんか?

解決するには?

スタックの重要な使い方は、サブルーチン呼び出しのネストです。

各サブルーチンは、そのサブルーチンのローカル変数のセットを持つことができます。これらの変数は、スタック上の スタックフレーム . 呼び出しの規則によっては、スタック上で引数を渡すものもあります。

サブルーチンを使うということは、呼び出し元、つまりリターンアドレスを追跡する必要があるということでもあります。 この目的のために専用のスタックを持つアーキテクチャもあれば、暗黙のうちに通常のスタックを使用するアーキテクチャもあります。MIPSではデフォルトでレジスタのみを使用しますが、非リーフ関数(つまり他の関数を呼び出す関数)では、リターンアドレスは上書きされます。したがって、元の値をローカル変数の間のスタックに保存する必要があります。呼び出しの規約で、あるレジスタの値を関数呼び出しの間保存しなければならないことが宣言されている場合もありますから、同様にスタックを使って保存したり復元したりすることができます。

次のようなC言語の断片があるとします。

extern void foo();
extern int bar();
int baz()
{
    int x = bar();
    foo();
    return x;
}

MIPSのアセンブリは、次のようになります。

addiu $sp, $sp, -8  # allocate 2 words on the stack
sw $ra, 4($sp)      # save $ra in the upper one
jal bar             # this overwrites $ra
sw $v0, ($sp)       # save returned value (x)
jal foo             # this overwrites $ra and possibly $v0
lw $v0, ($sp)       # reload x so we can return it
lw $ra, 4($sp)      # reload $ra so we can return to caller
addiu $sp, $sp, 8   # restore $sp, freeing the allocated space
jr $ra              # return