Search code examples
c#assemblymasm

How can I call an Assembly procedure from C# and get a result back?


I'm trying to call a very simple Assembly procedure from C# to get something returned from it.

Here's the C# code:

class Program
{
    static void Main(string[] args)
    {
        ulong test = Start();

        Console.WriteLine(test);
    }

    [DllImport(@"C:\dev\masm\basic.dll")]
    private static extern ulong Start();
}

Here's the Assembly (MASM) code:

.code
Start proc
    mov rax, 1
    ret
Start endp

end

I assemble and link from the console with the following command:

ml64 basic.asm /link /subsystem:console /entry:Start /out:basic.dll /dll /machine:x64

What's really interesting is that I'm able to successfully call a simple Assembly procedure that prints "Hello, World!" but doesn't return anything. However, when I try to call this procedure, even though I do specify an entry point in the DLL, I still get this error:

System.EntryPointNotFoundException: 'Unable to find an entry point named 'Start' in DLL 'C:\dev\masm\basic.dll'.'

I'm most likely missing something, but I can't figure it out.


Solution

  • You were so close! You need to mark the procedure as an export.

    .code
    Start proc export
        mov rax, 1
        ret
    Start endp
    
    end
    

    Console.WriteLine(test); now prints 1.

    You can verify that the Start procedure is exported by using a dev console and running DUMPBIN /HEADERS <DLL> and seeing it in the export section

    File Type: DLL
    
      Section contains the following exports for basic.dll
    
        00000000 characteristics
        FFFFFFFF time date stamp
            0.00 version
               1 ordinal base
               1 number of functions
               1 number of names
    
        ordinal hint RVA      name
    
              1    0 00001000 Start
    
      Summary
    
            1000 .rdata
            1000 .text
    

    An aside: the error you were getting

    System.EntryPointNotFoundException: 'Unable to find an entry point named 'Start' in DLL 'C:\dev\masm\basic.dll'.'
    

    doesn't actually have to do with the entry point of the dll (often called Main) but it's a PInvoke term that basically means "Hey, we couldn't find that exported "Start" method you told us to look for."