На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
  
> Вернуть значение из ассемблера в C# через С в Linux x64, .Net Core
    Добрый вечер!
    Привожу тексты программ (упрощённые).
    asm.s
    ExpandedWrap disabled
       .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
    ExpandedWrap disabled
      int foo(void)
      {
          extern int _start();
          return _start();
      }

    ExpandedWrap disabled
      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) после того, как она выведет сообщение на экран.
    Сейчас сообщение из Ассемблера не выводится и ничего не возвращается.
    Подскажите, куда копать?
    Предполагаю, что значение возвращается через стек.
    Сообщение отредактировано: Sunless -
      Думаю, дотнетчики больше в теме.
        Ну, я не вижу, чтобы asm.o линковался при создании lib.so.
        А выход из функции делается не через syscall exit, а через инструкцию ret.

        Добавлено
        Цитата Qraizer @
        Думаю, дотнетчики больше в теме.
        Мне кажется, он либу неправильно делает.

        Добавлено
        Sunless, будет ли это работать, если убрать asm вообще, а оставить чисто сишный код?
          В отношении связки C и ASM, думаю, мы разберёмся, но в отношении .NET с C я лично в своей компетенции сомневаюсь. И это помимо того, что это ещё и Mono. Кроме того, конкретно счас ситуация похожа на ту, что до связки C и ASM дело вообще пока не доходит.

          Добавлено
          Но да, sysexit() это сильно
            Предлагаю переформулировать "Вернуть значение из C в C#".
            Любой ассемблер инлайнится в Си. Верните значение из СИ!!!
            А потом смело си-ные функции пишите на асме.
              Дело в том, что с вызовами Си из Си Шарп и Ассемблера из Си проблем нет, а в связке 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


              Добавлено
              Кстати, инлайновые функции ассемблера я ещё не смотрел, но оптимизирует ли инлайновый код компилятор?
                Цитата Sunless @
                Кстати, инлайновые функции ассемблера я ещё не смотрел, но оптимизирует ли инлайновый код компилятор?
                Насколько мне известно, ни один компилятор не рискует что-либо менять в написанном человеком. Максимум – это просмотреть и попытаться учесть в генерируемым им коде вокруг вставки. Собственно, элементами между : во вставке ты можешь ему давать подсказки. Вот, почитай, если не в курсе.
                  Тогда инлайн не очень подходит. Я как раз рассчитываю смотреть оптимизацию компилятора в обучении.
                    https://gamedev.ru/code/articles/gcc_inline_asm?page=3 (там несколько страниц)
                    Цитата Sunless @
                    Кстати, инлайновые функции ассемблера я ещё не смотрел, но оптимизирует ли инлайновый код компилятор?
                    В базовой форме – не оптимизирует. В расширенной – может, если не указано volatile.
                      Упростил код.

                      my.c:
                      ExpandedWrap disabled
                        static int foo(void)
                        {
                        extern int _start();
                        return _start();
                        }


                      asm.s:
                      ExpandedWrap disabled
                        .text
                        .globl _start
                         
                        _start:
                        movq $60, %rax
                        xor %rdi, %rdi
                        syscall


                      C#:
                      ExpandedWrap disabled
                         [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", и при запуске программа ничего не выводит и не завершается.
                      Сообщение отредактировано: Sunless -
                        Попробуй сделать как тут описано:
                        https://stackoverflow.com/questions/1142520...tion-from-c-net

                        И вообще почему в Си у тебя функция static ? ты специально так написал?

                        Цитата Sunless @
                        Почему программа не видит функцию?

                        Добавлено Вчера, 22:07
                        Поставил EntryPoint="_start", и при запуске программа ничего не выводит и не завершается.

                        Почему EntryPoint="_start" а не EntryPoint="foo" ? ты какую функцию вызвать то хочешь, я так и не понял. В любом случае попробуй сделать как по ссылке выше, может поможет.
                          ExpandedWrap disabled
                            #define EXPORT __attribute__((visibility("default")))
                                EXPORT int foo(void);
                                int foo(void)
                                {
                                    extern int _start();
                                    return 1;
                                }

                          ExpandedWrap disabled
                            .text
                               .globl _start
                             
                            _start:              
                               movq $231, %rax
                               movq $1, %rdi
                               syscall

                          ExpandedWrap disabled
                             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.
                            По ссылке выше:
                            ExpandedWrap disabled
                              #include <stdio.h>
                               
                              void print(const char *message)
                              {
                                printf("%s\\n", message);
                              }


                            ExpandedWrap disabled
                              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 библиотеками.
                            Сообщение отредактировано: Wound -
                              Код примера работает. Из Си ассемблерная функция вызывается. Попробовал посмотреть с помощью 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 на С++, которая бы вызывала мою библиотеку на С?
                                С таким кодом работает.
                                ExpandedWrap disabled
                                  .text
                                     .globl _new
                                   
                                     _new:
                                     mov $1,%rax              
                                     ret

                                ExpandedWrap disabled
                                      #define EXPORT __attribute__((visibility("default")))
                                          EXPORT int foo(void);
                                          int foo(void)
                                          {
                                              extern int _new();
                                              return _new();
                                          }
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0440 ]   [ 16 queries used ]   [ Generated: 25.06.21, 09:46 GMT ]