9

少し前に、アセンブリルーチンを記述して、それをCプログラムとリンクすることを試みていましたが、標準のC呼び出しプロローグエピローグをスキップできることがわかりました。

    push ebp
    mov ebp, esp
    (sub esp, 4
    ...
    mov esp, ebp)
    pop ebp

すべてをスキップして、次espのようにアドレスを指定します

    mov eax, [esp+4]          ;; take argument
    mov [esp-4], eax          ;; use some local variable storage

かなりうまくいくようです。なぜこのebpが使用されるのebpですか?

4

3 に答える 3

11

スタックフレームを使用する必要はありませんが、確かにいくつかの利点があります。

まず、すべての関数がこれと同じプロセスを使用している場合、この知識を使用して、プロセスを逆にすることで一連の呼び出し(呼び出しスタック)を簡単に判別できます。call命令の後ESP、リターンアドレスを指し、呼び出された関数が最初に行うことはpush現在のものEBPであり、次ににコピーESPすることを知っていますEBP。したがって、いつでも、それが指すデータを見ることができます。EBPこれは前のデータであり、EBPそれEBP+4が最後の関数呼び出しの差出人住所になります。したがって、(さびたC ++を失礼します)のようなものを使用して、コールスタック(32ビットを想定)を出力できます。

void LogStack(DWORD ebp)
{
    DWORD prevEBP = *((DWORD*)ebp);
    DWORD retAddr = *((DWORD*)(ebp+4));

    if (retAddr == 0) return;

    HMODULE module;
    GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const char*)retAddr, &module);
    char* fileName = new char[256];
    fileName[255] = 0;
    GetModuleFileNameA(module, fileName, 255);
    printf("0x%08x: %s\n", retAddr, fileName);
    delete [] fileName;
    if (prevEBP != 0) LogStack(prevEBP);
}

これにより、その時点までの一連の呼び出し全体(まあ、それらのリターンアドレス)が出力されます。

さらに、EBP明示的に更新しない限り変更されないため(/とは異なり、 /のESP場合に変更されます)、スタック上のデータを参照する方が、相対的ではなく、相対的である方が通常は簡単です。後者の場合は、注意する必要があります。関数の開始と参照の間に呼び出された可能性のある/命令。pushpopEBPESPpushpop

他の人が述べているように、他の関数に対して行うスタックアドレスは、これらのアドレスのデータを上書きする可能性があるため、以下 スタックアドレスの使用は避けてください。代わりに、通常の関数で使用するためにスタック上のスペースを予約する必要があります。ESPcall

sub esp, [number of bytes to reserve]

この後、初期ESPとの間のスタックの領域ESP - [number of bytes reserved]は安全に使用できます。関数を終了する前に、一致するものを使用して予約済みのスタックスペースを解放する必要があります。

add esp, [number of bytes reserved]
于 2013-03-27T09:58:59.157 に答える
10

の使用はEBP、デバッガーがコールチェーン内のスタックフレームをトラバースできるため、コードをデバッグするときに非常に役立ちます。

これは、各呼び出し元のフレームポインタを関数にリンクする単一リンクリストを[作成]します。ルーチンのEBPから、関数の呼び出しスタック全体を回復できます。

http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Framesを参照してください。
特に、質問をカバーするリンク先のページ:http: //blogs.msdn.com/b/larryosterman/archive/2007/03/12 /fpo.aspx

于 2013-03-27T09:47:52.320 に答える
4

動作しますが、割り込みが発生すると、プロセッサはすべてのレジスタとフラグをスタックにプッシュし、値を上書きします。スタックには理由があります、それを使用してください...

于 2013-03-27T09:35:44.070 に答える