2

私はアセンブラの専門家ではなく、このトピックに関する知識はかなり浅いですが、値を返すだけの単純な関数呼び出しでMicrosoftVC++コンパイラが何をするのか興味がありました。

次の関数を使用しましょう。

unsigned long __stdcall someFunction ( void * args) {
    return 0;
}

これで、__stdcall呼び出し規約ではCALLEEがスタックの巻き戻しを担当し__cdecl、関数のCALLERでこれを処理することがわかりました。しかし、この例では、前者に固執したいと思います。

最適化されていないデバッグビルドでは、次の出力が生成されていることがわかりました。

unsigned long __stdcall someFunction (void * args) {
00A31730  push        ebp  
00A31731  mov         ebp,esp  
00A31733  sub         esp,0C0h  
00A31739  push        ebx  
00A3173A  push        esi  
00A3173B  push        edi  
00A3173C  lea         edi,[ebp-0C0h]  
00A31742  mov         ecx,30h  
00A31747  mov         eax,0CCCCCCCCh  
00A3174C  rep stos    dword ptr es:[edi]  
    return 0;
00A3174E  xor         eax,eax  
}
00A31750  pop         edi  
00A31751  pop         esi  
00A31752  pop         ebx  
00A31753  mov         esp,ebp  
00A31755  pop         ebp  
00A31756  ret         4

可能であれば、このコードスニペットについて説明してくれた人に感謝します。xorこのステートメントが実際にレジスタをリセットしeaxてゼロの戻り値を生成することを私は知っています。また、それret 4は私には自明です。edi、、esiおよびebxレジスターは、元の状態を保存するために前にプッシュされ、後にポップされるので、関数がそれらを自由に使用できるようになっていると思います。しかし、残りの部分については、私には手がかりがありません。

どんな答えでも大歓迎です!:)

ありがとう!

4

1 に答える 1

3

したがって、これらの行が何をするのかを尋ねています。

00A3173C  lea         edi,[ebp-0C0h]  
00A31742  mov         ecx,30h  
00A31747  mov         eax,0CCCCCCCCh  
00A3174C  rep stos    dword ptr es:[edi]

Visual C ++デバッグランタイムライブラリでは、初期化されていないスタックメモリが0xCCバイトを含むように初期化されます。これは、これらの手順が行うことです。

ASMコードの先頭には、スタックにバイトをsub esp,0C0h割り当てる命令があります。0xC0ただし、この関数で使用されるローカル変数はないので、これはどこから来るのでしょうか。Edit+Continueサポート用です。ローカル変数を追加してデバッグを続行できます。

0xCCオペコードはx86INT 3アセンブリ命令を意味するため、(誤ってバグが原因で)そのコードを実行しようとすると、プログラムはINT 3例外をスローし、デバッガーまたはOSによって処理されます。つまり、それは単なるランダムな値ではありません。

于 2012-06-09T17:37:53.407 に答える