Подключение и работа с dll на Masm для C#

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by piplnet, 16 Jun 2012.

  1. piplnet

    piplnet Member

    Joined:
    29 Jan 2012
    Messages:
    44
    Likes Received:
    17
    Reputations:
    10
    Всем доброго времени суток сегодня хотел бы начинающим разработчикам рассказать как к вашему проекту написанному на Visual studio 2008 C# подключить Dll написанной на ассемблере , итак начнем.

    Давайте откроем блокнот (Но лучше пользуйтесь бесплатным редактором WinAsm ссылку выложу в конце статьи)

    и напишим небольшой код вывода диалогового окна (Message Box)
    PHP:

    .386
    .MODEL flat,stdcall

    OPTION CASEMAP
    :NONE

    Include windows.inc
    Include user32.inc
    Include kernel32.inc
    IncludeLib user32
    .lib
    IncludeLib kernel32
    .lib

    .DATA
        HelloMsg db 
    "Эта наш первый DLL Модуль",0
        AppName db 
    " DLL_test ",0

    .code
        
    ;===== Здесь обработчик ошибок загрузки dll модуля здесь мы его упустим ====
    Dll_test proc hInstance:HINSTANCEreason:DWORDreserved1:DWORD

        ret 12
     Dll_test Endp
        
    ;=============================================================================

        ;========= 
    Здесь наша процедура которую мы и будем вызывать =================
     
    Hello proc
        invoke MessageBox
    ,NULL,addr HelloMsg,addr AppName,MB_OK
        ret 
     Hello endp
    ;=============================================================================

     
    End Dll_test
    То есть имя нашей функции которую мы будем вызывать Hello
    PHP:

     Hello proc
        invoke MessageBox
    ,NULL,addr HelloMsg,addr AppName,MB_OK
        ret 
     Hello endp
    теперь давайте от компилируем нашу будущую dll для этого создадим еще один файл (test.def) с таким содержимым
    PHP:
        LIBRARY Dll_test 
        EXPORTS Hello
    и батник для компиляции нашей библиотеки (test.bat) с таким содержимым
    PHP:

        c
    :/masm32/bin/ml //coff test.asm
        c
    :/masm32/bin/Link /SUBSYSTEM:WINDOWS /DLL /DEF:test.def test.obj
    запустите test.bat для компиляции после компиляции должен появиться файл test.dll
    Теперь давайте подключим нашу только-что созданную библиотеку к нашему проекту на c#
    откроем visual studio и создадим новый проект
    PHP:

    using System
    ;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace 
    Dll
     
    {
        public 
    partial class Form1 Form
        
    {
          public 
    Form1()
            {
              
    InitializeComponent();
            }
     
    //==== подключаем внешний dll модуль(test.dll) и импортируем функцию Hello ======
        
    [DllImport("test.dll")] public static extern void Hello();
        }
     }
    теперь давайте проверим как работает наша новая dll выкинем на форму кнопку (button) и двойным щелчком поней в обработчике сабытий впишем
    PHP:

        Hello
    ();
    теперь запустите проект и при нажатии кнопки должно выскочить диалоговое окно с надписью (Эта наш первый DLL Модуль)
    что означает что маша dll работает .
    теперь давайте рассмотрим как же передать параметры в эту библиотеку и принять их в нашей библиотеке:
    Для начала давайте передадим свой текст (переменную типа String)
    для этого слегка изменим нашу программу .
    PHP:

    using System
    ;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace 
    Dll
     
    {
       public 
    partial class Form1 Form
        
    {
          public 
    Form1()
          {
            
    InitializeComponent();
          }
    //==== подключаем внешний dll модуль(test.dll) ======
        
    [DllImport("test.dll")] public static extern void Hello(string text);

        private 
    void button1_Click(object senderEventArgs e)
          {
            
    string text "Это уже наш текст";
            
    Hello(text);
          }
        }
     }
    и изменим в файле test.asm
    PHP:

    .386

    .MODEL flat,stdcall
    OPTION CASEMAP
    :NONE

    Include windows.inc
    Include user32.inc
    Include kernel32.inc
    IncludeLib user32
    .lib
    IncludeLib kernel32
    .lib

    .DATA
        HelloMsg db 
    "Эта наш первый DLL Модуль",0
        AppName db 
    " DLL_test ",0

        text db 256 dup 
    (?);

    .
    code
     
    ;========= Здесь обработчик ошибок загрузки dll модуля здесь мы его упустим ========
    Dll_test proc hInstance:HINSTANCEreason:DWORDreserved1:DWORD

        ret 12
    Dll_test Endp
    ;======================================================================================

    ;========= 
    Здесь наша процедура которую мы и будем вызывать ==========================
    Hello proc string:DWORD
     
    ;--- API функция копирования строк
        INVOKE lstrcpy
    addr textstring
     
    ;-------------------------------------------

        
    invoke MessageBox,NULL,addr text,addr AppName,MB_OK
        ret 4
    Hello endp
    здесь мы в секцию .data резервируем новый участок памяти text размером в двойное слово DWORD и длиной в 256
    также мы добавили API функцию копирования строк и тем самым в нашу зарезервированную память (переменная text ) копируем строку которую мы передали из нашего проекта на c#, теперь опять компилируем и запускаем наш проект и теперь при нажатии на кнопку мы увидим текст который мы писали на c# .
    также передают и числовые переменные
    С#
    PHP:

    using System
    ;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace 
    Dll
    {
        public 
    partial class Form1 Form
        
    {
           public 
    Form1()
            {
             
    InitializeComponent();
            }
     
    //==== подключаем внешний dll модуль(test.dll) ======
        
    [DllImport("test.dll")] public static extern void Hello(string textint a);

          private 
    void button1_Click(object senderEventArgs e)
            {
             
    string text "Это уже наш текст";
             
    int a 2012;
             
    Hello(text,a);
            }
        }
    }
    И в masm test.asm
    PHP:

    .386

    .MODEL flat,stdcall
    OPTION CASEMAP
    :NONE

    Include windows.inc
    Include user32.inc
    Include kernel32.inc
    IncludeLib user32
    .lib
    IncludeLib kernel32
    .lib

    .DATA
        HelloMsg db 
    "Эта наш первый DLL Модуль",0
        AppName db 
    " DLL_test ",0

        text db 256 dup 
    (?);

        
    text1 db "%d",
        BUF DB 256 DUP
    (?)

    .
    code
     
    ;========= Здесь обработчик ошибок загрузки dll модуля здесь мы его упустим ========
    Dll_test proc hInstance:HINSTANCEreason:DWORDreserved1:DWORD

        ret 12
    Dll_test Endp
    ;======================================================================================

    ;========= 
    Здесь наша процедура которую мы и будем вызывать ==========================
    Hello proc string:DWORDa:DWORD

     
    ;--- API функция преобразования числа в строку ---
        
    invoke wsprintfaddr BUFaddr text1a
     
    ;-------------------------------------------------
        
    invoke MessageBox,NULL,addr BUF,addr AppName,MB_OK


     
    ;--- API функция копирования строк
        INVOKE lstrcpy
    addr textstring
     
    ;-------------------------------------------

        
    invoke MessageBox,NULL,addr text,addr AppName,MB_OK
        ret 4
    Hello endp
    ;=======================================================================================


    End Dll_test
    Здесь я добавил еще одну API функцию ( wsprintf) для преобразования числа в строку чтоб вы могли увидеть результат на экране
    теперь когда мы запустим проект то при нажатии увидим уже два диалоговых окна первое с числом 2012 . думаю тут вам все понятно.

    Теперь давайте рассмотрим как же из нашей библиотеки передать параметры в нашу программу на c#:
    Для этого немного изменим
    код на c#
    PHP:

    using System
    ;
    using System.Collections.Generic;
    using System.ComponentModel;using System.Data;using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace 
    Dll
    {
       public 
    partial class Form1 Form
        
    {
          public 
    Form1()
           {
             
    InitializeComponent();
           }
     
    //==== подключаем внешний dll модуль(test.dll) ======
        
    [DllImport("test.dll")] public static extern string Hello(string textint a);

        private 
    void button1_Click(object senderEventArgs e)
         {
            
    string text "Это уже наш текст";
            
    int a 2012;
     
    // Hello(text,a);
            
    label1.Text Hello(texta);
         }
        }
    }
    здесь как вы заметили мы изменили тип возврата нашей библиотеки
    ( [DllImport("test.dll")] public static extern string Hello(string text, int a);)
    с void на string
    и добавили компонент label "label1.Text = Hello(text, a);" чтоб можно было увидеть что нам вернет библиотека test.dll

    Также давайте внесем изменения и в проект нашей библиотеки на masm
    PHP:

    .386

    .MODEL flat,stdcall
    OPTION CASEMAP
    :NONE

    Include windows.inc
    Include user32.inc
    Include kernel32.inc
    IncludeLib user32
    .lib
    IncludeLib kernel32
    .lib

    .DATA
        HelloMsg db 
    "Эта наш первый DLL Модуль",0
        AppName db 
    " DLL_test ",0

        text db 256 dup 
    (?);

        
    text1 db "%d",
        BUF DB 256 DUP
    (?)

    .
    code
     
    ;========= Здесь обработчик ошибок загрузки dll модуля здесь мы его упустим ========
    Dll_test proc hInstance:HINSTANCEreason:DWORDreserved1:DWORD

        ret 12
    Dll_test Endp
     
    ;======================================================================================

     ;========= 
    Здесь наша процедура которую мы и будем вызывать ==========================
    Hello proc string:DWORDa:DWORD

     
    ;--- API функция преобразования цесла в строку ---
        
    invoke wsprintfaddr BUFaddr text1a
     
    ;-------------------------------------------------
        
    invoke MessageBox,NULL,addr BUF,addr AppName,MB_OK


     
    ;--- API функция копирования строк
        INVOKE lstrcpy
    addr textstring
     
    ;-------------------------------------------
        
    invoke MessageBox,NULL,addr text,addr AppName,MB_OK

     
    ;====== возвращаем строку из HelloMsg ========
        
    MOV EAX,OFFSET [HelloMsg]
        
    ret 4
    Hello endp
    ;===========================================================================================


    End Dll_test
    здесь как вы заметили мы Толька добавили одну строку
    MOV EAX,OFFSET [HelloMsg]
    то есть библиотека вернет текс хранящейся в HelloMsg а в нашем случии это "Эта наш первый DLL Модуль"
    также если вам нужно вернуть число то пишем
    MOV EAX,2012
    а на c# string меняем на int
    [DllImport("test.dll")] public static extern int Hello(string text, int a);
    и библиотека вернет нам число
    Из этого следует небольшое правило при программирование в ассемблере под windows что функция всегда возвращает то что находиться в регистре eax число или указатель на секцию в памети где находится строка :
    а на этом я пожалуй и закончу .

    Ссылки :
    Популярная среда разработки для ассемблера WinAsm
    Исходники к этой статье
    Masm
     
    #1 piplnet, 16 Jun 2012
    Last edited: 17 Jun 2012
    2 people like this.
  2. Jakeroid

    Jakeroid Member

    Joined:
    9 May 2009
    Messages:
    199
    Likes Received:
    12
    Reputations:
    1
    Спасибо.
    Только сделай код более читаемым, добавь табуляцию.
     
  3. piplnet

    piplnet Member

    Joined:
    29 Jan 2012
    Messages:
    44
    Likes Received:
    17
    Reputations:
    10
    :) подправил