9

私は ARM アセンブリを使用しています。ここでは、ARM 呼び出し規則に従っているサブルーチンを 1 つ作成する必要があります (これは、別の場所で別の高レベルの実装と統合する必要があります)。パラメーターと戻り値を渡します。

ここで、アセンブリを操作するときに一般的にわからないことがあります。

したがって、規則から、引数がレジスタ r0 - r4 から順に渡され、他の引数スタックが使用されることをよく理解している場合。戻り値は r0 に渡されます。

今ここに私が混乱しているものがあります。r0 のコンテキストを保存してからポップオフすることになっている場合、結果を返す方法はありません。これを行う唯一の方法は、最初の引数を破損することです。

どういうわけか回避策はありますか?

4

3 に答える 3

7

r0 で戻り値を返す場合、呼び出し元は、ユーザーがこれを行うことを期待しています。呼び出し元は、r0 が元の最初のパラメーターと同じ値を保持しているとは想定していません。これは、r0 が具体的に戻り値のある場所であるためです。

通常、 ARM 呼び出し規則では、サブルーチンが r0 から r3 ではなく、r4 から r11 を保持する必要があります。だから何の矛盾もありません。

于 2012-09-19T00:23:05.807 に答える
6

これを自分で試して、コンパイラが何をするか見てみませんか?

unsigned int fun ( unsigned int a, unsigned int b )
{
    return(a+b);
}

オブジェクトへのコンパイルと逆アセンブル

arm-none-eabi-gcc -O2 -c fun.c -o fun.o
arm-none-eabi-objdump -D fun.o 

結果は

00000000 <fun>:
   0:   e0810000    add r0, r1, r0
   4:   e12fff1e    bx  lr

2 つの入力 a と b は、r0 と r1 を使用して渡されます。r0-r4 は保持する必要はありません。特に r0 は戻り値であるため保持できません。そのため、C コードで必要な 2 つのオペランドが加算され、呼び出し規則で必要な結果が r0 に返されます。r0 = r0 + r1。

コンパイラは規則に準拠する必要があります。そうしないと、生成されるコードが機能しないため、コードをコンパイルして逆アセンブルするだけで、特定のコンパイラとターゲットの呼び出し規則についてかなりのことを知ることができます。

于 2012-09-19T04:11:31.333 に答える