質問

私はP /呼び出しを使用しているとき、私自身の呼び出し規約を指定できるようにする必要があることにより、

私は、ビジネスケースを持っています。具体的には、私は非標準のABIを使用する従来のDLLを持っている、と私は各機能の呼び出し規約を指定することが可能にする必要があります。

は、例えば、このDLL内の1つの機能は、スタックを介して他の部分と、EAXとEBXを介してその最初の二つの引数を受け付けます。別の機能は、スタック上の残りの部分と、ECXを経由して一つの引数を受け入れます。私は、これらの機能の数百を持っており、これらの機能にアクセスするために、私自身の中間ブリッジDLLを書く避けたい。

私の他のオプションは、手でロールバックする明白な理由のために望ましくない独自のカスタムP /呼び出しを、となります。

すべてのヘルプは高く評価され、感謝、

役に立ちましたか?

解決

私は、カスタムP /呼び出しで何を意味するのか理解していないが、私はあなたがインラインアセンブリで非管理C ++せずに逃げることができるか見ることができません。ほとんどすべてが32ビット値として渡されるので、あなたは、機能ごとに一つに並置として、各関数のシグネチャのために一つだけのプロキシを書いて逃げるかもしれません。それとも、XMLからプロキシを生成するコードジェネレータを書くことができます。すべてのプロキシ機能は本当に簡単になりますので、私は、しかし、このバージョンは、あまりにも好ましくない見ることができません。

int RealFunction(int param1, const char * param2, char param 3);

int MyFunction(int param1, int param2, int param3) { // argument types do not matter as long as they are not doubles or structures
   __asm {
      mov eax, param1
      mov ebx, param2
      push param3
      call RealFunction
      ; depending on calling convention, you might need to do add esp, 12 here
      ; if RealFunction does not return its result in eax, you will need to do mov eax, <wherever the return value is> here
   }
}

他のヒント

私は別のDLLなしで何をしたい達成するための何の組み込み方法がないかなり確信しています。私は、ランタイムシステムがサポートしているもの以外呼び出し規約を指定する方法を見ていませんでした。

私はしばらく前に呼び出し規約についての学習と呼び出し規則を変換するために、いくつかのコードを書きました。コードは、ラッパーライブラリはリフレクションを使用して、特別なC#のラッパーから呼び出される特殊な裸のスタブメソッドのメソッドを呼び出す/新しいPを放出する(Marshal.getdelegateforfunctionpointerが働いて得ることができませんでした)を発します。これは、パラメータを修正してから、実際にメソッドを呼び出します。

ここでは、Cコードがあります。私は便利なC#の部分を持っていない:(私はコードが吸うかもしれないので、一度にあまりにもアセンブラを学んでいた:)

typedef struct
{
    USHORT ParameterOneOffset;  // The offset of the first parameter in dwords starting at one
    USHORT ParameterTwoOffset;  // The offset of the second parmaeter in dwords starting at one
} FastCallParameterInfo;



    __declspec( naked,dllexport ) void __stdcall InvokeFast()
{
    FastCallParameterInfo paramInfo;
    int functionAddress;
    int retAddress;
    int paramOne, paramTwo;
    __asm
    {
        // Pop the return address and parameter info.  Store in memory.
        pop retAddress;
        pop paramInfo;
        pop functionAddress;

        // Check if any parameters should be stored in edx                          
        movzx ecx, paramInfo.ParameterOneOffset;     
        cmp ecx,0;
        je NoRegister;  

        // Calculate the offset for parameter one.
        movzx ecx, paramInfo.ParameterOneOffset;    // Move the parameter one offset to ecx
        dec ecx;                                    // Decrement by 1
        mov eax, 4;                                 // Put 4 in eax
        mul ecx;                                    // Multiple offset by 4

        // Copy the value from the stack on to the register.
        mov ecx, esp;                               // Move the stack pointer to ecx
        add ecx, eax;                               // Subtract the offset.
        mov eax, ecx;                               // Store in eax for later.
        mov ecx, [ecx];                             // Derefernce the value
        mov paramOne, ecx;                          // Store the value in memory.

        // Fix up stack
        add esp,4;                                  // Decrement the stack pointer
        movzx edx, paramInfo.ParameterOneOffset;    // Move the parameter one offset to edx
        dec edx;                                    // Decrement by 1
        cmp edx,0;                                  // Compare offset with zero
        je ParamOneNoShift;                         // If first parameter then no shift.

    ParamOneShiftLoop:
        mov ecx, eax;
        sub ecx, 4;
        mov ecx, [ecx]
        mov [eax], ecx;                             // Copy value over
        sub eax, 4;                                 // Go to next 
        dec edx;                                    // decrement edx
        jnz ParamOneShiftLoop;                      // Loop
    ParamOneNoShift:
        // Check if any parameters should be stored in edx                          
        movzx ecx, paramInfo.ParameterTwoOffset;     
        cmp ecx,0;
        je NoRegister;  

        movzx ecx, paramInfo.ParameterTwoOffset;    // Move the parameter two offset to ecx
        sub ecx, 2;                                 // Increment the offset by two.  One extra for since we already shifted for ecx
        mov eax, 4;                                 // Put 4 in eax
        mul ecx;                                    // Multiple by 4

        // Copy the value from the stack on to the register.
        mov ecx, esp;                               // Move the stack pointer to ecx
        add ecx, eax;                               // Subtract the offset.
        mov eax, ecx;                               // Store in eax for later.
        mov ecx, [ecx];                             // Derefernce the value
        mov paramTwo, ecx;                          // Store the value in memory.           

        // Fix up stack
        add esp,4;                                  // Decrement the stack pointer
        movzx edx, paramInfo.ParameterTwoOffset;    // Move the parameter two offset to ecx
        dec edx;                                    // Decrement by 1
        cmp edx,0;                                  // Compare offset with zero
        je NoRegister;                              // If first parameter then no shift.
    ParamTwoShiftLoop:
        mov ecx, eax;
        sub ecx, 4;
        mov ecx, [ecx]
        mov [eax], ecx;                             // Copy value over
        sub eax, 4;                                 // Go to next 
        dec edx;                                    // decrement edx
        jnz ParamTwoShiftLoop;                      // Loop


    NoRegister:
        mov ecx, paramOne;                          // Copy value from memory to ecx register
        mov edx, paramTwo;                          // 
        push retAddress;
        jmp functionAddress;
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top