34

Is there some method of using C source mixed with inline asm (this is not C++ code) in a C# app? I'm not picky about how it gets done, if it requires compiling the C/asm into a DLL alongside the C# app, so be it. I'm aware there's no provision for using assembly inside C#, hence this question.

Sample code of what I'm trying to incorporate:

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

There are some pointer/variable declarations in the C code before that function is declared, but beyond that it's all inline assembly, the declarations are used in the assembly code if that effects anything.

Objective is to pass 'inputData' from C# and then have access to 'outputData' in the C# program in some fashion. Normally we'd just rewrite the assembler code in native C# but we're on a tight schedule for getting a prototype together and don't see any reason to reinvent the wheel right away if we can temporarily use the existing C/assembly code in some fashion.

6
  • Though I'm not sure how, I think you have to make your not-c# code into a dll and call it. You can't just slap in code for another language. By the way you can use pointers in c#, but seeing you just want to use existing code, don't bother (also I would verbally abuse you if you did) Commented Sep 16, 2013 at 19:54
  • Compiling the C/asm into a DLL is probably the easiest option (it's technically possible to allocate writable|executable memory and go that route, but there's not much point unless your code is dynamic). You already gave your own answer though, so I don't really get this question. Use a DLL, problem solved, right? Commented Sep 16, 2013 at 19:55
  • I've used C dlls in c# code, its pretty straight forward, just make sure you use the Marshall CDecl Commented Sep 16, 2013 at 20:00
  • Well, if you want to get technical, sure I answered my own question by saying 'use a DLL' but I was expecting there to be pitfalls and gotchas with said approach. All examples I found so far were dealing with managed C++ code, no mention of C with inline assembly, and I was unsure if a C compiler would build a proper DLL that was usable with a C# app. Commented Sep 16, 2013 at 20:48
  • 1
    Ok if you put it that way.. I suppose it's a bit of a pitfall/gotcha that you can't just add it as a reference as with managed DLLs. Commented Sep 17, 2013 at 8:23

1 Answer 1

43

It's actually very easy and does not even require 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

I have written a blog post on this.

Sign up to request clarification or add additional context in comments.

10 Comments

Ensure you are compiling it for 32bit
this is the real answer to the question. the other just show how to use dll written in c\c++ that use asm. this is show how to use c# and asm altough this is kind of dirty. because unlike c\c++ which actualy compile the code as is. but anyway this is a good trick
For 64bit try to replace with: 0x8d, 0x04, 0x11, //lea eax, DWORD PTR [rcx+rdx] 0xC3 //ret
After: 0x55, // 0 push ebp it needs: 0x8b, 0xec, // 1 mov ebp, esp Otherwise it fails in NET Core
That's not really inline assembly, more like inline hex. True inline assembly gives you access to all the features of an assembler, including syntax checking, labels, maybe macros. Not to mention the potential security issue with making an entire 4K page both writable and executable, or how UWP applications might not be allowed to use VirtualProtect.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.