5

ASMの概念を理解しようとしていますが、MSVCによって生成された逆アセンブルを観察していると、完全には理解できないことがあります。これが私のテストケースです:

#include <tchar.h>
#include <conio.h>
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    int v1 = 1;
    int v2 = 2;
    int v3 = 3;
    int v4 = 4;
    int v5 = 5;
    int v6 = 6;
    int v7 = 7;
    int v8 = 8;
    int v9 = 9;
    int v10 = 10;
    int v11 = 11;
    int v12 = 12;
    int v13 = 13;
    int v14 = 14;
    int v15 = 15;
    int v16 = 16;

    int sum = v1+v2 * (v3+v4 * (v5+v6 * (v7+v8 * (v9+v10 * (v11+v12 * (v13+v14 * (v15+v16)))))));

    _getch();
    return 0;
}

これは次のようなものを生成します:

    mov eax, v1
    mov edx, v3
    mov ecx, v5
    mov ebx, v7
    mov esi, v9
    mov edi, v11 // all 6 available registers are filled
    mov dword ptr [ebp-60h), eax // free eax   <<<<<<
    mov eax, v15 // fill it again
    add eax, v16
    imul eax, v12
    (...)

だから、私の質問は:「<<<<<<」でマークされた行でコンパイラは何をしますか?私の推測では、レジスタ値を格納する変数が作成されています。それは、を使用するときにスタック上にあるように見えますがebp、「グローバル変数」のようなものですか、それとも現在のスコープ(フレーム)の変数ですかそれだけ?

前もって感謝します。

4

1 に答える 1

4

MSVCは、レジスタを適切なメモリにスピルします。ブロックスコープを持つ変数を保持しているレジスタをスピルしている場合はスタックに、グローバルを保持している場合は固定オフセットにスピルします。コンパイラはいつでも、どの変数がどのレジスタにあるかを認識しています。

スレッドと再入可能性のために、予測できない数のローカル変数が存在する可能性があるため、ローカル変数をグローバルメモリにスピルすることはできません。コンパイラーは一時的にグローバル変数をスタックスロットにスピルできるかもしれませんが、これはスレッドが存在する場合は非常に複雑です。

于 2012-11-13T12:04:29.933 に答える