4

CPU スタック上の関数にパラメーターを渡すと、

パラメータを設定すると、JSR は戻りアドレスをスタックに置きます。つまり、関数では、他の項目を削除する前に、スタックの一番上の項目 (戻りアドレス) を取得する必要があります)

戻り値は慣例により register に格納されますD0

たとえば、次の正しい方法があります。

...
|Let’s do some addition with a function,
MOVE.L #4, -(SP)
MOVE.L #5, -(SP)
JSR add
        |the result of the addition (4+5) is in D0 (9)
...

add: 
    MOVE.L   (SP)+,  A1     |store the return address
                            |in a register
    MOVE.L  (SP)+, D0       |get 1st parameter, put in D0
    MOVE.L  (SP)+, D2       |get 2nd parameter, put in D2

    ADD.L      D2, D0       |add them, 
                            |storing the result in D0
    MOVE.L  A1, -(SP)       |put the address back on the 
                            |Stack
    RTS                     |return
4

3 に答える 3

8

パラメータをポップしないという意味で、スタックからパラメータを「取り出す」ことはありません。通常、プロシージャへのエントリ ポイントでスタックの一番上を指すようにフレーム レジスタを割り当て、フレーム ポインタからの既知の定数オフセットでパラメータにアクセスします。次に、インデックスは、そこにあることがわかっているリターンアドレスを「スキップ」します。

たとえば、手順にいるときの架空のアセンブリで。スタックが減少しているとします。

...
argument2
argument1
ret addr     <---- stack pointer 

したがってargument1、オフセットsp+4(32 ビットを想定)、argument2オフセットsp+8などにアクセスするだけです。これらの呼び出し規則は既知であるため、これらのオフセットはコードにハードコードされており、効率的に計算できます。

ローカル変数もスタックにプッシュし、パラメーターのインデックスを別の場所で変更したくないため、フレーム ポインターは非常に便利です。そのため、フレーム ポインターはプロシージャーの実行中に安定したアンカーを提供します。

于 2010-04-09T05:33:29.140 に答える
6

いいえ。

呼び出し先(ターゲット関数)は通常、自身の引数を削除する責任を負いません。発信者はそれらをそこに置き、それらを削除する方法を最もよく知っている人です。

また、68000では、スタックへの相対オフセットを使用して簡単に読み取ることができ、スタックから引数を物理的に削除(ポップ)する必要はありません。これは、リターンアドレスを非常にうまく「ダブルバッファリング」しなければならないという問題を回避します。

したがって、コードは次のように読み取る必要があります。

    MOVE.L #4, -(SP)
    MOVE.L #5, -(SP)
    JSR add
    ADDQ.L #8, SP           |remove the arguments from the stack, both at once.

...

add: 
    MOVE.L  4(SP), D0       |get 1st parameter, put in D0
    ADD.L   8(SP), D0       |add the 2nd parameter
    RTS                     |return
于 2010-04-09T12:15:41.653 に答える
3

いいえ、パラメーターを確認するためにスタックからパラメーターをポップする必要はありません。@eliが言うように、通常の手順は「フレームポインタ」レジスタを使用することです。実際、68k には、LINKそれを容易にするように設計された命令 ( ) さえあります。これは、(a) 前のフレーム ポインターを保存し、(b) 現在のスタック ポインターをフレーム ポインターにコピーし、(c) をデクリメントする単一の命令です。指定された量だけポインターをスタックして、ローカル変数用の余地を残します。

C コードと対応する 68000 アセンブラの例を次に示します。

于 2010-04-09T05:41:50.350 に答える