Devin Jenson's WebLog

That One Guy

Dynamically Writing and Executing Native Assembly in C#

Generally, executing native assembly in C# is bad because you lose all the benefits of the managed world. In the cases where it is impossible to perform something in C#, it is better to make a C++ DLL. That said, the new method Marshal.GetDelegateForFunctionPointer() in the .NET Framework v2.0 opens up the possibility for dynamically writing and executing assembly code. Consider the following basic C function:


int __declspec(noinline) __stdcall MyAdd(int x, int y)
{
    return x + y;
}

The C compiler will compile the code into assembly. Though the code which gets compiled may vary from compiler to platform, for x86 it will usually have this basic form:


Instruction                 Code Bytes   Comment
------------------------------------------------------------------------------
mov eax,dword ptr [esp+8] ' 8B 44 24 08  Load the x into eax
mov ecx,dword ptr [esp+4] ' 8B 4C 24 04  Load the y into ecx
add eax,ecx               ' 03 C1        Add eax and ecx, result goes into eax
ret 8                     ' C2 08 00     Pop x and y off the stack, return eax

The instructions listed are disassembly copied from the VC++ debugger. The code bytes are what actually executes. The idea is to take those code bytes, write them into a native buffer, acquire a delegate for that buffer, and finally execute the delegate. Here is sample code to run these code bytes from C#:


using System; 
using System.Runtime.InteropServices;




class Program
{
    private delegate Int32 MyAdd(Int32 x, Int32 y);

    private static void Main() 
    {
        // A simple Add function
        Byte[] myAddNativeCodeBytes = new Byte[]
        {
            0x8B, 0x44, 0x24, 0x08, // mov eax,dword ptr [esp+8]
            0x8B, 0x4C, 0x24, 0x04, // mov ecx,dword ptr [esp+4]
            0x03, 0xC1,             // add eax,ecx
            0xC2, 0x08, 0x00        // ret 8
        };

        // We need to push the code bytes into a native buffer
        IntPtr myAddNativeCodeBytesPtr = IntPtr.Zero;

        try
        {
            // Allocate the native buffer
            myAddNativeCodeBytesPtr =
                Marshal.AllocCoTaskMem(myAddNativeCodeBytes.Length);

            // Push the code bytes over
            Marshal.Copy(myAddNativeCodeBytes, 0,
                myAddNativeCodeBytesPtr, myAddNativeCodeBytes.Length);

            // Get a function pointer for the native code bytes
            MyAdd myAdd = (MyAdd)Marshal.GetDelegateForFunctionPointer(
                myAddNativeCodeBytesPtr, typeof(MyAdd));

            // Call the native code bytes
            Int32 result = myAdd(4, 5);

            // Did it work?
            Console.WriteLine("Result: {0}", result);
        }

        finally
        {
            // Free the native buffer
            if (myAddNativeCodeBytesPtr != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(myAddNativeCodeBytesPtr);
                myAddNativeCodeBytesPtr = IntPtr.Zero;
            }
        }
    }
}

In this sample I just used Marshal.AllocCoTaskMem(), but one should actually P/Invoke VirtualAllocEx and VirtualProtectEx to ensure the page where the code exists has PAGE_EXECUTE access. Additionally the above sample is targetted to my personal x86 machine, and will not run on x64 or any other platform for that matter.

Published Tuesday, July 12, 2005 11:44 PM by devinj

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Mike's Dump said:

I thought this was kind of cool (geeky cool of course). Don't know if I'd ever have a need for it but...
July 13, 2005 9:24 AM
 

Mark.Michaelis said:

Thanks... GetDelegateForFunctionPointer() is just what I was looking for and I had previously not noticed it.

For those who may need it, I have posted the VirtualAllocEx() and VirtualProtectEx() code at http://mark.michaelis.net/Blog/PermaLink.aspx?guid=1a243cc3-fc47-4c67-a6a1-688598b1b8cf.
July 15, 2005 5:17 AM
 

Jamestsai Blog said:

Dynamically Writing and Executing Native Assembly in C# A research OS written in C# C# for the Dummy...

February 9, 2007 4:32 AM
 

Dynamically Writing and Executing Native Assembly in C# « Mike’s Dump said:

September 8, 2007 8:02 PM
 

Vaibhav Gaikwad said:

Fantastic...so who says asm code cant be exectuted in managed code :))

Thanks a lot for the example.

August 15, 2008 4:28 AM
 

Dave Hybrid said:

Great post, really helped me understand, thanks!

September 18, 2008 2:46 PM
 

it help said:

A really well explained article and has given me a nice idea for a project!

October 20, 2008 7:07 PM
 

Devin Jenson s WebLog Dynamically Writing and Executing Native | Green Tea Fat Burner said:

June 9, 2009 3:24 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit

© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker