在 C# 中使用 C/内联汇编

问题描述 投票:0回答:1

是否有某种方法可以在 C# 应用程序中使用 C 源代码与内联汇编(这是不是C++ 代码)?我对如何完成并不挑剔,如果需要将 C/asm 与 C# 应用程序一起编译成 DLL,那就这样吧。我知道 C# 中没有使用汇编的规定,因此这个问题。

我试图合并的示例代码:

SomeFunc(unsigned char *outputData, unsigned char *inputData, unsigned long inputDataLength)
{
    _asm
    {
        //Assembly code that processes inputData and stores result in outputData
    }
}

在声明该函数之前,C 代码中有一些指针/变量声明,但除此之外都是内联汇编,如果有任何影响,这些声明将在汇编代码中使用。

目标是从 C# 传递“inputData”,然后以某种方式访问 C# 程序中的“outputData”。通常我们只是用原生 C# 重写汇编代码,但我们制作原型的时间安排很紧,如果我们可以暂时使用现有的 C/汇编代码,那么没有任何理由立即重新发明轮子。一些时尚。

c# c assembly interop
1个回答
41
投票

其实很简单,甚至不需要反思。

[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int AssemblyAddFunction(int x, int y);

[DllImport("kernel32.dll")]
private static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);

byte[] assembledCode =
{
    0x55,               // 0 push ebp            
    0x8B, 0x45, 0x08,   // 1 mov  eax, [ebp+8]   
    0x8B, 0x55, 0x0C,   // 4 mov  edx, [ebp+12]  
    0x01, 0xD0,         // 7 add  eax, edx       
    0x5D,               // 9 pop  ebp            
    0xC3                // A ret                 
};

int returnValue;
unsafe
{
    fixed (byte* ptr = assembledCode)
    {
        var memoryAddress = (IntPtr) ptr;

        // Mark memory as EXECUTE_READWRITE to prevent DEP exceptions
        if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress,
            (UIntPtr) assembledCode.Length, 0x40 /* EXECUTE_READWRITE */, out uint _))
        {
            throw new Win32Exception();
        }

        var myAssemblyFunction = Marshal.GetDelegateForFunctionPointer<AssemblyAddFunction>(memoryAddress);
        returnValue = myAssemblyFunction(10, -15);
    }               
}

Console.WriteLine($"Return value: {returnValue}"); // Prints -5

我已经就此写了一篇博客文章

© www.soinside.com 2019 - 2024. All rights reserved.