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

标签 c# c assembly interop

是否有一些方法可以在 C# 应用程序中混合使用 C 源代码和内联 asm(这不是 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”。通常我们只是用 native C# 重写汇编程序代码,但我们的时间很紧,无法将原型(prototype)放在一起,如果我们可以暂时使用现有的 C/汇编代码,我们认为没有任何理由立即重新发明轮子一些时尚。

最佳答案

其实很简单,甚至不需要反射(reflection)。

        [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

我已经写了一篇关于这个的博文:https://esozbek.me/inline-assembly-in-csharp-and-dotnet/

关于c# - 在 C# 中使用 C/内联汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18836120/

相关文章:

assembly - 在 assembly 中使用 LODSB 需要什么?

c# - updatepanel 触发导致完全回发而不是部分回发

c# - 如何跨程序集使用 Ninject

c - 我正在使用MinGw编译器,每当我尝试调试代码时都会出错。以及为什么在我使用mingw时它的位置是cygwin

c - 释放动态分配的矩阵

c++ - 为什么C/C++会自动将char/wchar_t/short/bool/enum类型转换为int?

c - C如何跨平台?

c# - 如何在C#中获取对象的所有简单属性

c# - 将大型 C# winforms 应用程序升级到 WPF 的最简单方法是什么

assembly - 汇编中的 int 10h , ah as 0d 始终返回 0 作为鼠标指针下像素的颜色