2011-12-04 9 views
1

memset()と同じように、メモリのブロックを指定した値に設定する関数をアセンブリで作成しようとしていますが、スタックから3番目の引数を取得するときに(fastcall呼び出し規約を使用します)レジスタECXは、何らかの歪んだ値を取得します。__fastcallでESPが壊れないようにするにはどうすればよいですか?

インラインアセンブリを使用してVisual Studioにコードを挿入すると、関数が呼び出されたときにESPが大幅に変更されていることがわかります。 最初の2つの引数は何の問題もなくECXとEDXに入れられていますが、問題を引き起こしているのは3番目の引数だけです。

私はVSでデバッグ中にレジスタに値を手動で設定すると、メモリブロックが正しい値で満たされていることが分かります。

私はアセンブリが比較的新しいので、私のコードはおそらく少しばかげていますが、誰もこの問題を解決する方法を知っていますか?

コードは以下の通りです:

 


    #ifdef __GNUC__ 
    #define __fastcall __attribute__((fastcall)) // 'Cause I'm a M$ fanboy 
    #endif 

    void __fastcall memset(void *pDest, int iValue, int iSize) 
    { 
     __asm 
     { 
      ; Assume the pointer to the memory is stored in ECX 
      ; Assume the value is stored in EDX 
      ; Assume the size of the block is stored on the stack 

       mov eax, esi  ; Put ESI somewhere it won't be touched (I think) 

       mov esi, ecx  ; Move the address of the memory into ESI 
       xor ecx, ecx  ; Zero ECX 

       pop ecx    ; Get the size of the block into ECX. ECX is our loop counter 

      memset_count: 
       cmp ecx, 0   ; If we are at the end of the block, 
       jz memset_return ; Jump to return 

       mov [esi], edx  ; Move our value into the memory 
       inc esi    ; Otherwise, increment out position in the memory 
       dec ecx    ; Decrement out counter 
       jmp memset_count ; Start again 

      memset_return: 
       mov esi, eax  ; Restore ESI 
       add esp, 4   ; Remove our third argument from the stack 
       ret 
     } 
    } 

    #define ret return 

    int main(int argc, char **argv) 
    { 
     char szText[3]; 

     /* 
     __asm 
     { 
      push 3 
      mov edx, 65 
      lea ecx, szText2 
      call memset 
     } 
     */ 
     memset(&szText, 'A', 3); 

     ret 42; 
    } 

 
+0

'#define ret return'?どのように怠惰なことができますか? – Dani

+0

VSで逆アセンブリビューを有効にして、コードから何が生成されるかを確認できます。 –

答えて

2

と呼ばれるコードのスタック上の最初のものは、コールの戻りアドレスになります。もう一つは最初の議論です。

ESPの変更を避け、「間違ったものをポップする」問題を解決するには、「mov ecx、[esp + 4]」(「pop ecx」ではなく)のようなものを試してみてください。

+0

__declspec(naked)を追加した後、 'mov ecx、[esp + 4]'は完全に動作しました。ありがとう。 – vs49688

2

問題は、これが関数内にあるということです。コンパイラはすでにいくつかの変数をポップしています。 gccは変数を参照する手段を持っていますが、MSVCについてはわかりません

+0

なぜ私はそれを見落としたのかわかりません - 予期せぬコンパイラの混乱がプロローグ/エピローグでどういうことがあるのか​​も知れません。 – Brendan

+0

これは__declspec(naked)として宣言するのを忘れていたことを思い出しました。これを実行すると、コンパイラは関数が実行された前後に悩むことがなくなりました。 – vs49688

関連する問題