2016-06-15 15 views
0

私は、次のコードを持っているが、そのメモリのブロックをXORすることになっている:C/C++インラインアセンブラ不適切なオペランドの型

void XorBlock(DWORD dwStartAddress, DWORD dwSize, DWORD dwsKey) 
{ 
DWORD dwKey; 
__asm 
{ 
    push eax 
    push ecx 
    mov ecx, dwStartAddress   // Move Start Address to ECX 
    add ecx, dwSize     // Add the size of the function to ECX 
    mov eax, dwStartAddress   // Copy the Start Address to EAX 

    crypt_loop:       // Start of the loop 
     xor byte ptr ds:[eax], dwKey  // XOR The current byte with 0x4D 
     inc eax       // Increment EAX with dwStartAddress++ 
     cmp eax,ecx      // Check if every byte is XORed 
    jl crypt_loop;      // Else jump back to the start label 

    pop ecx // pop ECX from stack 
    pop eax // pop EAX from stack 
} 
} 

はしかし、引数dwKeyは私にエラーを与えます。たとえば、dwKeyが0x5Dに置き換えられた場合、コードは完全に機能します。

+0

CまたはC++で書いたよりも速いと思われる理由は何ですか?シーザー暗号が数ミリ秒で壊れる可能性があることを考えると、どれほど速いかは問題ではありません。 –

+1

'DWORD dwsKey'はタイプミスですか?余分な 's'が間違いだと思われる?ローカル変数 'DWORD dwKey;'を削除しますか? –

+0

このコードのポイントは何ですか?コンパイラが4バイトxor、つまりSSE2 PXORを使用しないようにするために、ゆっくりとasmを書いていますか? –

答えて

4

私はあなたに2つの問題があると思います。

まず、 "xor"は2つのメモリオペランドを取ることができません(ds:[eax]はメモリの場所、dwKeyはメモリの場所です)。第2に、byteを必要とすることを示すために "byte ptr"を使用しましたが、DWORDを使用しようとしていて、アセンブリはそれらを自動的に変換できません。

したがって、値を8ビットレジスタにロードしてから実行する必要があります。例:

void XorBlock(DWORD dwStartAddress, DWORD dwSize, DWORD dwsKey) 
{ 
    DWORD dwKey; 
    __asm 
    { 
     push eax 
     push ecx 
     mov ecx, dwStartAddress   // Move Start Address to ECX 
     add ecx, dwSize     // Add the size of the function to ECX 
     mov eax, dwStartAddress   // Copy the Start Address to EAX 
     mov ebx, dwKey     // <---- LOAD dwKey into EBX 

     crypt_loop :       // Start of the loop 
      xor byte ptr ds : [eax], bl  // XOR The current byte with the low byte of EBX 
      inc eax       // Increment EAX with dwStartAddress++ 
      cmp eax, ecx      // Check if every byte is XORed 
      jl crypt_loop;      // Else jump back to the start label 

     pop ecx // pop ECX from stack 
     pop eax // pop EAX from stack 
    } 
} 

dwKeyはコード内で初期化されていないようですが、多分あなたはちょうど "mov bl、0x42"でなければなりません。また、レジスタをプッシュしてポップする必要があるかどうかもわかりません。私はあなたがMSVC++インラインアセンブラで壊れるのを許されているレジスタを覚えていません。

しかし、結局のところ、Alan Stokes氏は彼のコメントで正しいと思います。この場合、アセンブリは実際にはC/C++コードよりも実際には高速ではありません。コンパイラはこのコードを単独で簡単に生成することができ、実際には予期しない最適化を実行して、「明白な」アセンブリ(たとえばloop unrolling)よりも高速に実行できることがあります。

+0

私は '__asm'は、必要に応じて' __asm'文の中で使われているレジスタを保存して復元することを考えています。 MSVCは__asmを分析してレジスタの使用状況を判断します。手動で処理する必要があるレジスタ(セレクタ以外)は、ESPとEBPのみです。 GCCはインラインアセンブラ文を解析しませんが、MSVCは実行します。 –

+2

"C/C++関数で__asmを使用してアセンブリ言語を記述する場合、EAX、EBX、ECX、EDX、ESI、またはEDIレジスタを保持する必要はありません。"(https://msdn.microsoft.com/en- us/library/k1a8ss06.aspx)。このページはまた、自動的に保存/復元する必要のあるレジスタを最適化するためにMichaelが分析することを意味しています。 – Steven

+0

ありがとう、これは問題を解決しました。 – Zer0Mem0ry

関連する問題