
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.227.251.94] |
![]() |
|
Сообщ.
#1
,
|
|
|
Добрый вечер!
Привожу тексты программ (упрощённые). asm.s ![]() ![]() .data message: .ascii "ASSEMBLY OUTPUT MESSAGE" .equ one, 1 len = . - message .text .globl _start _start: movq $one, %rdi movq $one, %rax movq $len, %rdx movq $message, %rsi syscall #sys_write movq $74, %rax #rdi == 1 syscall #fsync movq $60, %rax xor %rdi, %rdi syscall #exit my.c ![]() ![]() int foo(void) { extern int _start(); return _start(); } ![]() ![]() using System.Runtime.InteropServices; class Program{ [DllImport("lib.so")] public static extern int foo (); static void Main(string[] args) { System.Console.WriteLine(foo()); } } Момент сборки: Цитата gcc -c -fpic my.c asm.s -nostartfiles && gcc -shared -o lib.so my.o Программа при запуске выводит только Цитата Hosting components are already initialized. Re-initialization to execute an app is not allowed. Этот текст встречается в .net здесь https://github.com/dotnet/core-setup/blob/m...xr/fx_muxer.cpp Цель - вызвать программу на Си из Си Шарпа, которая вызовет программу на Ассемблере, чтобы из последней считать вычисленное значение (здесь - код завершения программы 0) после того, как она выведет сообщение на экран. Сейчас сообщение из Ассемблера не выводится и ничего не возвращается. Подскажите, куда копать? Предполагаю, что значение возвращается через стек. |
![]() |
Сообщ.
#2
,
|
|
Думаю, дотнетчики больше в теме.
|
![]() |
Сообщ.
#3
,
|
|
Ну, я не вижу, чтобы asm.o линковался при создании lib.so.
А выход из функции делается не через syscall exit, а через инструкцию ret. Добавлено Цитата Qraizer @ Мне кажется, он либу неправильно делает. Думаю, дотнетчики больше в теме. Добавлено Sunless, будет ли это работать, если убрать asm вообще, а оставить чисто сишный код? |
![]() |
Сообщ.
#4
,
|
|
В отношении связки C и ASM, думаю, мы разберёмся, но в отношении .NET с C я лично в своей компетенции сомневаюсь. И это помимо того, что это ещё и Mono. Кроме того, конкретно счас ситуация похожа на ту, что до связки C и ASM дело вообще пока не доходит.
Добавлено Но да, sysexit() это сильно |
Сообщ.
#5
,
|
|
|
Предлагаю переформулировать "Вернуть значение из C в C#".
Любой ассемблер инлайнится в Си. Верните значение из СИ!!! А потом смело си-ные функции пишите на асме. |
Сообщ.
#6
,
|
|
|
Дело в том, что с вызовами Си из Си Шарп и Ассемблера из Си проблем нет, а в связке 3-х языков не работает.
Добавлено Вызов Ассембелера из Си - https://www.devdungeon.com/content/how-mix-c-and-assembly Вызов Си из Си Шарп - https://ru.stackoverflow.com/questions/8870...0%be%d0%b4%d0%b Полная команда у меня такая: Цитата gcc -Wall -Werror -c -s -fpic -fpie -pie -e main -Ofast -m64 -nostartfiles -nodefaultlibs -nostdlib my.c asm.s -x none -Wa,-mintel64,-mtune=corei7,-msyntax=att,-mmnemonic=att,-march=corei7,--64 -shared Добавлено Кстати, инлайновые функции ассемблера я ещё не смотрел, но оптимизирует ли инлайновый код компилятор? |
![]() |
Сообщ.
#7
,
|
|
Цитата Sunless @ Насколько мне известно, ни один компилятор не рискует что-либо менять в написанном человеком. Максимум – это просмотреть и попытаться учесть в генерируемым им коде вокруг вставки. Собственно, элементами между : во вставке ты можешь ему давать подсказки. Вот, почитай, если не в курсе. Кстати, инлайновые функции ассемблера я ещё не смотрел, но оптимизирует ли инлайновый код компилятор? |
Сообщ.
#8
,
|
|
|
Тогда инлайн не очень подходит. Я как раз рассчитываю смотреть оптимизацию компилятора в обучении.
|
![]() |
Сообщ.
#9
,
|
|
https://gamedev.ru/code/articles/gcc_inline_asm?page=3 (там несколько страниц)
Цитата Sunless @ В базовой форме – не оптимизирует. В расширенной – может, если не указано volatile. Кстати, инлайновые функции ассемблера я ещё не смотрел, но оптимизирует ли инлайновый код компилятор? |
Сообщ.
#10
,
|
|
|
Упростил код.
my.c: ![]() ![]() static int foo(void) { extern int _start(); return _start(); } asm.s: ![]() ![]() .text .globl _start _start: movq $60, %rax xor %rdi, %rdi syscall C#: ![]() ![]() [DllImport("lib.so")] public static extern int foo (); Команда сборки: Цитата as --64 -o asm.o asm.s && gcc -c -fpic my.c -o my.o && gcc -shared -o lib.so my.o asm.o Получаю исключение dotnet run Unhandled exception. System.EntryPointNotFoundException: Unable to find an entry point named 'foo' in shared library 'lib.so'. at Program.foo() Почему программа не видит функцию? Добавлено Поставил EntryPoint="_start", и при запуске программа ничего не выводит и не завершается. |
Сообщ.
#11
,
|
|
|
Попробуй сделать как тут описано:
https://stackoverflow.com/questions/1142520...tion-from-c-net И вообще почему в Си у тебя функция static ? ты специально так написал? Цитата Sunless @ Почему программа не видит функцию? Добавлено Вчера, 22:07 Поставил EntryPoint="_start", и при запуске программа ничего не выводит и не завершается. Почему EntryPoint="_start" а не EntryPoint="foo" ? ты какую функцию вызвать то хочешь, я так и не понял. В любом случае попробуй сделать как по ссылке выше, может поможет. |
Сообщ.
#12
,
|
|
|
![]() ![]() #define EXPORT __attribute__((visibility("default"))) EXPORT int foo(void); int foo(void) { extern int _start(); return 1; } ![]() ![]() .text .globl _start _start: movq $231, %rax movq $1, %rdi syscall ![]() ![]() 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); } } Тут я делаю gcc -shared -fpic -o lib.so my.c asm.s затем dotnet run и получаю в консоли 1 Если верну в Си return _start();, то получаю сообщение Hosting components are already initialized. Re-initialization to execute an app is not allowed. |
Сообщ.
#13
,
|
|
|
По ссылке выше:
![]() ![]() #include <stdio.h> void print(const char *message) { printf("%s\\n", message); } ![]() ![]() using System; using System.Runtime.InteropServices; public class Tester { [DllImport("libtest.so", EntryPoint="print")] static extern void print(string message); public static void Main(string[] args) { print("Hello World C# => C++"); } } Начни с этого примера. Если это заработает, значит проблема в импорте функции из ассемблера или в линковке ассемблерной библиотеки в Сишную. Возможно у тебя не находит ассемблерную функцию в контексте C# кода. Попробуй может сделать статическую либу ![]() А из Си вызывается ассемблерная функция? Можно еще конечно посоветовать юзать C++/Cli как прокладку между C# и C/Asm, но я не знаю умеет ли она работать с *.so библиотеками. |
Сообщ.
#14
,
|
|
|
Код примера работает. Из Си ассемблерная функция вызывается. Попробовал посмотреть с помощью strace свою программу на C#, но там exit_group(1) не вызывается, -значит, что до ассемблера не доходит. Со статической библиотекой исключение Unhandled exception. System.DllNotFoundException: Unable to load shared library 'libtest.so' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibtest.so: cannot open shared object file: No such file or directory
at Program.print(String message) Добавлено Как сделать библиотеку для Linux на С++, которая бы вызывала мою библиотеку на С? |
Сообщ.
#15
,
|
|
|
С таким кодом работает.
![]() ![]() .text .globl _new _new: mov $1,%rax ret ![]() ![]() #define EXPORT __attribute__((visibility("default"))) EXPORT int foo(void); int foo(void) { extern int _new(); return _new(); } |