Создание Привет Мировой библиотечной функции в блоке и вызов его от C#

Скажем, мы используем NASM, как они делают в этом ответе: как записать привет мир в блоке под окнами.

Я получил несколько мыслей и вопросов относительно блока, объединенного с c# или любыми другими языками .NET в этом отношении.

В первую очередь, я хочу смочь создать библиотеку, которая имеет следующую функцию HelloWorld это берет этот параметр:

  • Имя:

В C# сигнатура метода была бы looke как это: void HelloWorld(string name) и это распечатало бы что-то как

Привет Мир с имени

Я искал вокруг немного, но не могу найти, что так много хорошего и чистого материала для этого запускает меня. Я знаю некоторый основной блок до главным образом gasвсе же.

Так любые указатели в правильном направлении в значительной степени apprechiated.

Подвести итог его

  • Создайте стандартную программу в ASM (NASM), который берет один или несколько параметров
  • Скомпилируйте и создайте библиотеку вышеупомянутой функциональности
  • Включайте библиотеку в любой язык .NET
  • Назовите включенную библиотечную функцию

Дополнительные материалы

  • Как каждый обрабатывает возвращаемый значения?
  • Действительно ли возможно записать встроенный ASM-метод?

При создании библиотек в блоке или c, Вы действительно следуете за определенным "пред определенный" путь, c, звонящий convetion, корректный?

5
задан Community 23 May 2017 в 11:47
поделиться

4 ответа

Что-то вроде этого должно дать вам рабочую DLL:

extern _printf

section .text
global _hello
_hello:
    push ebp
    mov ebp, esp

    mov eax, [ebp+12]
    push eax
    push helloWorld
    call _printf
    add esp, 8
    pop ebp
    ret

export _hello

helloWorld: db 'Hello world from %s', 10, 0

Затем вам просто нужно вызвать функцию 'hello' с помощью P / Invoke. Он не очищается после себя, поэтому вам нужно установить CallingConvention на Cdecl; вам также нужно указать, что вы используете строки ANSI. Не тестировалось, но должно работать нормально.

using System.Runtime.InteropServices;

namespace Test {
    public class Test {
        public static Main() {
            Hello("C#");
        }

        [DllImport("test.dll", EntryPoint="hello", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
        public static extern Hello(string from_);
    }
}
11
ответ дан 18 December 2019 в 11:54
поделиться

Это очень хороший вопрос и заслуживает моего голоса. Что касается вашего вопроса, единственный способ сделать это, как указал Коди на свою процедуру ассемблера, - это создать DLL на основе этого, а затем использовать p / Invoke с использованием таких операций, как

[DllImport("mylib.dll")]

и т. Д. Однако, к сожалению, из-за природы C # или любого другого языка в этом отношении среда выполнения CLR использует управляемый код. Было бы неудобно иметь CLR или ассемблер для настройки кадра стека, регистров, а затем перекрестного перехода из собственного мира в управляемый мир. Это было бы нелегко, но если кто-то видел подобное, оставьте, пожалуйста, комментарий в конце моего ответа, и я внесу в него соответствующие поправки.

И поэтому, насколько мне известно, нет способа встроить процедуру ассемблера ассемблером в этот контекст, используя системные регистры, такие как eax, ebx, фреймы стека и т. Д., В код CLR, как и в примере из код, который Коди предоставил в своем ответе. В этом случае это было бы верно с C / C ++:

void foo(void){
   _asm{
     xor ecx, ecx
     mov eax, 1
     ....
   }
}

Было бы неплохо сделать это с точки зрения CLR, как это, чтобы оптимизировать код дальше, по крайней мере теоретически, но это было бы непреодолимой задачей для CLR для размещения подобных вещей есть одно исключение ... это можно сделать с помощью управляемого компилятора C ++, который может это сделать, но в любом случае НЕ из VB.NET/C#:

private void mycsfunction(string s){
    // Managed code ahoy
    StringBuilder sb = new StringBuilder(s);
    ......
    _asm{
        push ebp
        mov ebp, esp
        lea edx, offset sb
        ....
        mov eax, 1
        pop ebp
    }
}

Однако , хотя по этой теме, это можно сделать для генерации кода IL для собственного ассемблера, теперь, когда я пишу это, я не уверен на 100%, что это можно сделать в обратном порядке. См. здесь для подробное описание того, как это может произойти

Но , однако, единственный способ работы над сборкой CLR - это рукописный ввод кода IL и его компиляция, то есть непосредственно ассемблер среды выполнения CLR в очень значительной степени так же, как родной ассемблер может быть вызван родным языком (читайте двоичные файлы НЕ-CLR), см. эту статью здесь , чтобы узнать, как это сделать.

1
ответ дан 18 December 2019 в 11:54
поделиться

Сначала я расскажу об основных рекомендациях, как делать то, что вы хотите ... затем я попытаюсь объяснить, как это сделать в примере Hello World.

Первым шагом будет написание функции и создание из нее dll. Функция в сборке должна соответствовать одному из стандартов вызова, stdcall является наиболее распространенным (вы можете узнать больше о stdcall и других стандартах вызова здесь ). Пример создания dll с помощью asm можно найти здесь

Вторым шагом будет импорт метода на управляемый язык с помощью P / Invoke. Вы можете прочитать об этом здесь

И все ..

Теперь для упомянутого примера вам нужно будет создать функцию asm, которая принимает все входные параметры и передает их какой-либо другой функции, которая знает как печатать в стандартный вывод (printf из стандартной библиотеки c lib, как указано выше, или с использованием вызовов winapi, например здесь )

После этого вам нужно будет импортировать dll в C #, как описано выше. Особое внимание следует уделять кодировке символов для строк и очистке данных. Все они упомянуты в третьей ссылке, которую я предоставил (раздел текста маршалинга).

Дополнительная часть:

  • Обработка возвращаемых значений зависит от об используемых соглашениях о вызовах
  • Невозможно написать встроенную сборку с помощью C #. Однако вы можете написать их с помощью Managed C ++.
3
ответ дан 18 December 2019 в 11:54
поделиться

На мой взгляд, у вас двоякий вопрос:

  1. Как мне написать функцию с помощью сборки и поместить ее в DLL?
  2. Как мне вызвать функцию в неуправляемая DLL из управляемого C #?

Ответ на вопрос 2 - использовать P / Invoke. По этой теме доступно множество документации и руководств, например http://msdn.microsoft.com/en-us/magazine/cc164123.aspx

0
ответ дан 18 December 2019 в 11:54
поделиться