2017-02-05 9 views
1

から関数へ分岐するとき、スタック全体を保護するために、私は、次のARM64アセンブリコードを持っている:ARM64:どのように組み立て

.text 
.arch armv8-a 
.type testARM64, STT_FUNC 
.global testARM64 

testARM64: 
arg1 .req x0 
arg2 .req x1 
arg3 .req x2 
arg4 .req x3 
arg5 .req x4 
arg6 .req x5 
tmp .req x9 


    mov tmp, #0 

    mov x0, #1 
    bl debugAssembly 

    mov tmp, #2 

    ret 

.unreq arg1 
.unreq arg2 
.unreq arg3 
.unreq arg4 
.unreq arg5 
.unreq arg6 
.unreq tmp 

私からそれを呼び出す:

#include <stdlib.h> 

void testARM64(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); 

void debugAssembly(int a) { 
    fprintf(stderr, "Debug 0x%d\n", a); 
} 

int main(int argc, char **argv) { 
    testARM64(0, 0, 0, 0, 0, 0); 
    return 0; 
} 

どのように保護することができます。 debugAssemblyに分岐するときにスタック全体?私は何の議論の数と何かを実行することができますプッシュ/ポップのARM命令の同等だろうと何か私は何の一時レジスタと私のアセンブリ内で行うのですか? (私は車線を保護/保存する必要はありません)。

+0

ARMプロシージャコールスタンダードは、http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdfに役立ちます。 – InfinitelyManic

答えて

0

fp regとリンクレジスタを保存する必要があります。stp x29、x30、[sp、#0x10]のようなものがよくあります。他の関数を呼び出して関数を終了する前に値を復元する前に、プラットフォームがfpにx29を使用していると仮定します。それ以外の場合は、他の機能を実行すると、呼び出し元のリターンアドレスを保持するリンクレジスタが上書きされます。あなたのプラットフォームがフレームポインタを使用していなくても、スタックに2つのレジスタを保存したいので、ABIはおそらくスタックポインタの16バイトアライメントを必要とします。

あなたのコンパイラが生成したいくつかの簡単な関数を逆アセンブルし、独自の手書きルーチン用のモデルとしてその命令を使用することをお勧めします。

+0

gccの使用方法を理解するためにgcc -Sを使用しましたが、現在の状況に特有のものです。私が変更したレジスタの数。スタック/レジスタの状態を気にせずに同じデバッグコードを貼り付けることができます。それで、なぜ私の質問は「スタック全体」と言ったのですか? – gregoiregentil

+0

"スタック全体"の意味を理解できませんでした。関数のプロローグ(関数の開始)にすべての不揮発性(または「呼び出し先保存済み」)レジスタを保存し、関数の終わり(関数の終わり)でそれらを復元することができます。これは安全ですあなたの手書きのすべての機能のために。あなたのABIがAAPCSに準拠していると仮定すると、InfinitelyManicがリンクしているAAPCSは、救われる必要があるものの良い参考情報です。あなたが保存する必要があるよりも多くのレジスタを節約することは非効率的であることに注意してください。そして、手書きアセンブリを書く唯一の理由は、重要な効率関数のためです。 –

関連する問題