Как выполнить код на Assembler из кода C# под Linux

Пиццикато Алексея Лота

Как выполнить код на Assembler из кода C# под Linux

Для работы понадобится ОС Linux и установленные в ней компиляторы gcc, g++. Проверить наличие компилятора можно командой whereis, а установить - командой sudo apt install в терминале. Имеется простейший код на GNU Assembler, возвращающий 1 (файл asm.s):
.text
   .globl _new
   _new: 
   mov $1,%rax              
   ret
Хотим запустить его в C# с помощью PInvoke. Для этого потребуется промежуточная динамическая библиотека на языке C с кодом (файл my.c):
        #define EXPORT __attribute__((visibility("default")))
        EXPORT int foo(void);
        int foo(void)
        {
            extern int _new();
            return _new();
        }
Эти два файла нужно собрать в shared library (файл lib.so) командой
gcc -shared -fpic -o lib.so my.c asm.s
Полученный файл lib.so нужно подложить в папку с исполняемым файлом результирующей программы на C#. У меня это подкаталог проекта /bin/Debug/netcoreapp3.1/. Код на C# для запуска функции _new выглядит так:
    using System.Runtime.InteropServices;
    class Program{
    [DllImport("lib.so")] public static extern int foo ();
     static void Main(string[] args)
            {
                int code = foo();
    System.Console.WriteLine(code);
    }
    }
Запускается он командой dotnet run, если у вас установлена исполняемая среда .NET Core. В консоли вы увидите 1. Чтобы добавить прослойку между C# и C в виде кода на C++, нужно добавить в проект файл my.cpp с кодом:
   extern "C"{
        #define EXPORT __attribute__((visibility("default")))        
        EXPORT int foocpp(void)
        {
            extern int foo();
            return foo();
        }}
и заменить в коде C# название внешней функции foo на foocpp. Тогда изменится команда сборки и будет выглядеть так:
g++ -shared -fpic -o lib.so my.cpp -x c my.c -x assembler asm.s
После чего запускаем dotnet run и видим 1 в консоли.