Calling a Delphi DLL from C# produces unexpected results

前端 未结 7 1267
庸人自扰
庸人自扰 2021-01-05 03:29

I have a Delphi DLL that I did not write, but need to call from a C# ASP.NET 3.5 app. Here is the function definition I got from the developers:

function Cr         


        
7条回答
  •  再見小時候
    2021-01-05 04:10

    I was messing around the other day trying to learn about calling conventions and I wrote some methods to convert between various ones. Here is one for StdCall->FastCall.

    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;
        }
    }
    

    }

提交回复
热议问题