2

Visual Studio を使用し、C++ からアセンブリを呼び出しています。引数をアセンブリに渡すとき、最初の引数は ECX にあり、2 番目の引数は EDX にあることを知っています。最初に ECX を EAX にコピーしないと、2 つのレジスタを直接比較できないのはなぜですか?

C++:

#include <iostream>

extern "C" int PassingParameters(int a, int b);

int main()
{
    std::cout << "The function returned: " << PassingParameters(5, 10) << std::endl;

    std::cin.get();
    return 0;
}

ASM: 2 つのレジスタを直接比較すると、間違った値が返されます。

.code
PassingParameters proc
    cmp edx, ecx
    jg ReturnEAX

    mov eax, edx

ReturnEAX:
    ret
PassingParameters endp
end

しかし、このように書くと正しい値が得られ、2 つのレジスタを直接比較できます。なぜでしょうか?

.code
PassingParameters proc
    mov eax, ecx ; copy ecx to eax.
    cmp edx, ecx ; compare ecx and edx directly like above, but this gives the correct value.
    jg ReturnEAX

    mov eax, edx

ReturnEAX:
    ret
PassingParameters endp
end
4

1 に答える 1

5

最初のバージョンで を使用すると、関数に入ったときとまったく同じ状態になりjgますeax(つまり、ほとんど手がかりがありません)。戻り値は通常 eax であるため、 が取得されるたびに未定義の戻り値が返さjgれます。言い換えれば、あなたが書いたものは大まかに次のようなものです:

int PassingParameters(int a, int b) { 
    if (a < b)
        return a;
}

この場合、a==b、またはの場合a>b、戻り値はガベージです。

2 番目のコード シーケンスでは、1 つの値を eax にロードしています。次に、jg が取得されない場合は、他の値を eax にロードしています。どちらの方法でも、戻り値はいずれかの入力パラメーターになります (どちらが大きいかに応じて)。言い換えれば、あなたが持っているものは次のものとほぼ同等です:

int PassingParameters(int a, int b) { 
   if (a<b)
       return a;
    return b;
}

PSまた、あなたのコードは64ビットコードではなく、x86のように見えることにも注意してください。64 ビット コードの場合、EAX や ECX などではなく、RAX や RCX などを使用する必要があります。

于 2013-01-25T04:16:58.667 に答える