Как выполнить код на 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 в консоли.