Chapter 8: Dynamic Link Libraries and Their Development in Assembly Language

image from book  Download CD Content

Dynamic Link Libraries (DLL) are the essential and, perhaps, the most important part of Windows operating systems. They serve as a depositary of procedures, including WIN API functions, and provide powerful tools for writing effective applications. We will not dwell on the principles of DLL building and functioning, because there are many publications devoted to this topic. It is much more interesting to learn how to create DLL on your own. Dynamic link libraries, regardless of the way they are created, can be used with any compiler or application.

The use of DLL provides a programmer with considerable advantages in development and replication of a program code:

  • The size of an executable code can be reduced, because different applications can use the same library functions.

  • Program code contained in DLL is less labor- intensive than similar functions used in several applications.

  • Large projects can be better structured and become more manageable.

  • The implementation of new functions to be added to the applications becomes easier: it is enough to release a new version of DLL.

Dynamic link libraries are usually written in HLL (C, Pascal, etc.), although it is possible to develop them in assembler. We will consider the key issues of development and use of DLLs in following order:

  1. Initialization of DLL.

  2. Export of functions and data from DLL.

  3. Calling DLL with load-time dynamic linking.

  4. Calling DLL with run-time dynamic linking.

Each DLL must have an entry point. In Visual C++ .NET 2003, such an entry point is the DllMain function. DLL, written in assembler MASM, has an entry point called LibMain . The operation system calls these functions in the following cases:

  • When an application calls DLL for the first time

  • When the process linked to this library creates a new stream

  • When the process linked to this library deletes a stream

  • When DLL is removed from memory

Functions and data can be exported from DLL in any of the following ways:

  • Creating a DEF file whose EXPORT section contains the names of exported elements

  • Creating references to exported elements defined with the keyword _ _declspec (dllexport)

The method using a DEF file is now considered obsolete, though it is still utilized. The handling and configuring of a DEF file can turn out to be a difficult task, especially when different compilers are used for DLL and application developments.

The _ _declspec method is preferable for work with 32-bit applications and can be applied in most cases. The 32-bit versions of compilers (not only C++ .NET) can export data, functions, classes, and functions ” members of classes from DLL by using the _ _declspec(dllexport) keyword. This keyword inserts instruction to export the project to the object file, which allows manipulating it without the DEF file.

Dynamic link library can be loaded simultaneously with the application (load-time dynamic linking) or during the application executing (run-time dynamic linking).

Load-time dynamic linking requires the user to specify whether the application is DLL-dependent. For this purpose, the program project must include the import library (LIB file). Compiler C++ .NET will create the import library automatically during the DLL generation. The LIB file is not an ordinary static library. It does not contain a program code ”only references to all functions exported from the DLL file, in which the code resides. Import libraries are usually smaller than DLL files.

When launching an application, Windows finds necessary DLLs and calculates addresses of each reference to the library. Searching for the library is implemented in the application working directory first, and then in the Windows system directory.

To illustrate the method of load-time dynamic linking, we will develop two programs ”a dynamic link library (named impdll ) and the application test_impdll , which uses the impdll . DLL includes the sub2dll function that returns the difference of two integers used as parameters. We will generate our application as a Win32 Project using the Application Wizard of C++ .NET 2003. Define the type of the application as DLL and create the project files. The DLL source code is very simple and includes only the DllMain entry point. To make the DLL workable , we have to include the sub2dll function s source code in the project. The final version of the code is shown in Listing 8.1, where the sub2dll function is in bold.

Listing 8.1: Source code for imdll.dll
image from book
 // impdll.cpp : Defines the entry point for the DLL application.  #include "stdafx.h"  BOOL APIENTRY DllMain(HANDLE hModule,                         DWORD ul_reason_for_call,                         LPVOID lpReserved                       }  {      return TRUE;  }  int _ _declspec(dllexport) sub2dll(int i1, int i2)   {   return (i1-i2);   }  
image from book
 

Function sub2dll must be accessible from other modules, so it is to be declared with a keyword _ _declspec(dllexport) (note that two underscore characters precede the declaration).

We will develop an application calling the sub2dll function from image from book  impdll.dll . As a template, we will take the Win32 Project and compile it as a console application (named as test_impdll ). The source code of the application is shown in Listing 8.2.

Listing 8.2: Using impdll in the application test_impdll
image from book
 // test_impdll.cpp : Defines the entry point for the console application.  #include "stdafx.h"  int _ _declspec(dllimport) sub2dll(int i1, int i2);  int _tmain(int argc, _TCHAR* argv[])  {   int isub;   int i1 = 56;   int i2 =   34;   printf("i1 = %d, ", i1);   printf("i2 = %d\n", i2);   printf("i1   i2 = %d", sub2dll(i1, i2));   getchar();   return 0;  } 
image from book
 

The sub2dll function is to be imported from another module (in Listing 8.2, it is in bold face type). An application project also has to include the image from book  impdll.lib import library. Also, the image from book  impdll.dll file must be saved in the application-working directory or in the system directory.

A window of the running application is shown in Fig. 8.1.

image from book
Fig. 8.1: Application window that demonstrates how to use the impdll.dll import library

You can create a DLL using MASM. Assembly code is very efficient for writing DLLs: this considerably improves performance and reduces the size of a code. We will develop an assembly version of image from book  impdll.dll in MASM. The source code of the DLL template (named as templdll.asm ) is simple and is shown in Listing 8.3.

Listing 8.3: Template of DLL developed in MASM
image from book
 ;-------------------------templdll.asm----------------- .686  .model flat, C  option casemap:none  .code  LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD   mov EAX, 1   ret  LibMain Endp  End LibMain 
image from book
 

The template includes only the LibMain function, which is an entry point of the DLL. Listing 8.3 shows the simplest implementation of a dynamic link library.

Compilation and linking of DLL should be done by the following commands:

 ml/c/coff templdll.asm  link/SUBSYSTEM:WINDOWS/DLL templdll.obj 

Our templdll.dll library created with MASM is just a stub that cannot do anything useful. Therefore, we will change the DLL source code. Include in DLL the source code of function calculating the difference of two integers ( name it sub2 ). The content of the file modified (named as sub2.asm ) is shown in Listing 8.4.

Listing 8.4: The modified variant of DLL s assembly version
image from book
 ;-------------------------sub2.asm----------------- .686 .model flat, C  option casemap:none  .code  LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD   mov EAX, 1   ret  LibMain endp  sub2 proc   push EBP   mov  EBP, ESP   mov  EAX, [EBP+8]  ; i1   sub  EAX, [EBP+12] ;   i2   pop  EBP   ret  sub2 endp  end LibMain 
image from book
 

To use DLL with C++ .NET application, we have to specify the programming language in the model directive:

 .model flat, C 

This means that the calling convention _cdecl is used, which is why the last command ret of the sub2 function goes without parameters and the stack is cleared by the main program in C++. The source code of the sub2 function is simple and no additional explanation is required.

To create the import library, we need a file with a description of exported functions. Such files have a DEF extension. We will create it and name it image from book  sub2.def . The file should include the following lines:

 LIBRARY sub2  EXPORTS       sub2 

The DEF file is needed only for creation of the import library and will not be used anymore. The following commands implement the assembly of DLL:

 ml/c/coff sub2.asm  link/SUBSYSTEM:WINDOWS/DLL/DEF:sub2.def sub2.obj 

If the compilation is successfully completed, we will have the files:

 sub2.obj  sub2.lib  sub2.dll  sub2.exp 

Now, we will test the DLL, using the method of load-time dynamic linking. To do this, we will need the image from book  sub2.dll and image from book  sub2.lib files. Develop a console application in C++ .NET using Application Wizard. It is necessary to include the image from book  sub2.lib file into the project and copy image from book  sub2.dll in an application-working directory. The source code is shown in Listing 8.5.

Listing 8.5: Calling of a function from DLL using the load-time dynamic linking
image from book
 // test_asmdll.cpp: Defines the entry point for the console application.  #include "stdafx.h"  extern "C" int sub2 (int i1, int i2);  int _tmain (int argc, _TCHAR* argv [])  {  int i1 =   23;  int i2 =   19;  printf (" i1 = %d, ", i1);  printf (" i2 = %d\n ", i2);  printf (" i1   i2 = %d ", sub2(i1, i2));  getchar ();  return 0;  } 
image from book
 

Pay attention to the following line:

 extern "C" int sub2 (int i1, int i2); 

The keyword _ _declspec(dllimport) is not necessary to use for libraries generated with the assembler: It is enough to declare function as external and forbid the name declaration. The application window is shown in Fig. 8.2.

image from book
Fig. 8.2: Demonstration of using the load-time dynamic linking of DLL

You can include in DLL the functions written in assembler and stored in a separate object module. The most common way is to generate a DLL template in C++ .NET and include in it the functions written in assembler. (Macro assembler saves these as OBJ files). Such combining allows you to vary the size of a source code and operating-system resources and performance simultaneously with modest development time.

Consider an example, in which the main program in C++ calls three functions from DLL. The first function (named add2 ) returns the sum of two integers. The second function (named as sub2 ) returns the difference between two integers. Suppose that function sub2 is written in assembler and compiled as a separate OBJ file. The third function (named submul5 ) uses the result returned by sub2 for multiplying it by 5. We will use the Application Wizard of Visual C++ .NET again and develop the DLL that contains functions described above. The template of DLL created by Wizard is shown as a file image from book  addsub.cpp in Listing 8.6.

Listing 8.6: DLL template
image from book
 // addsub.cpp: Defines the entry point for the DLL application.  #include "stdafx.h"  BOOL APIENTRY DllMain (HANDLE hModule,                         DWORD ul_reason_for_call,                         LPVOID lpReserved)  {   return TRUE;  } 
image from book
 

Now insert the code for calling functions into the DLL source code shown in Listing 8.6. The add2 function is defined as follows :

 extern "C" _ _declspec(dllexport) int add2 (int i1, int i2)  {   return (i1+i2);  }; 

The sub2 function is placed in a separate assembly module and declared as

 extern "C" int sub2 (int i1, int i2); 

The source code of the sub2 function is shown in Listing 8.7.

Listing 8.7: Function sub2
image from book
 ;-------------------sub2.asm------------- .686  .model flat, C    public sub2  .code  sub2 proc      push EBP      mov  EBP, ESP      mov  EAX, DWORD PTR [EBP+8]      sub  EAX, DWORD PTR [EBP+12]      pop  EBP      ret   sub2 endp  end 
image from book
 

We will save the source code of the sub2 function in the image from book  sub2.asm file and compile it using MASM. Then we will include the OBJ module obtained in our DLL project.

The function, as mentioned above, implements the subtraction of two integers and returns their difference. This result is used by the exported function submul5 :

 extern "C" _ _declspec (dllexport) int submul5 (int i1, int i2)  {    return (sub2 (i1, i2) *5);  }; 

The source code of DLL with all changes is presented in Listing 8.8.

Listing 8.8: Using the object modules in DLL
image from book
 // addsub.cpp: Defines the entry point for the DLL application.  #include "stdafx.h"  BOOL APIENTRY DllMain (HANDLE hModule,                         DWORD ul_reason_for_call,                         LPVOID lpReserved)  {      return TRUE;  }  extern "C" _ _declspec (dllexport) int add2 (int i1, int i2)  {   return (i1+i2);  };  extern "C" int sub2 (int i1, int i2);  extern "C" _ _declspec (dllexport) int submul5 (int i1, int i2)  {   return (sub2 (i1, i2) *5);  }; 
image from book
 

After compilation of the DLL project, we will get the image from book  addsub.dll and the image from book  addsub.lib import library.

Now, we will develop a test application using functions from the image from book  addsub.dll library. The dialog-based application will include four Edit Control elements, four Static Text controls and a Button . Link the Edit Control controls to integer variables i1 , i2 , add2Edit , and submul5Edit . In the editable fields that correspond to variables i1 and i2 , we will enter integer values, and in the editable fields boxes corresponding to output values, we will see the results of calling functions add2 and submul5 . All of these manipulations are implemented by the button handler ” OnBnClickedButtonl . This is a key issue; the full source code of the program is shown in Listing 8.9.

Listing 8.9: More complicated example where load-time dynamic linking is used
image from book
 // testdllDlg.cpp: implementation file  #include "stdafx.h"  #include "testdll.h"  #include "testdllDlg.h"  #include ".\testdlldlg.h"  int _ _declspec(dllimport) add2 (int i1, int i2);  int _ _declspec (dllimport) submul5 (int i1, int i2);  #ifdef _DEBUG  #define new DEBUG_NEW  #endif  // CAboutDlg dialog used for App About  class CAboutDlg: public CDialog  {  public:         CAboutDlg ();  // Dialog Data         enum {IDD = IDD_ABOUTBOX};         protected:         virtual void DoDataExchange (CDataExchange* pDX); // DDX/DDV support  // Implementation  protected:         DECLARE_MESSAGE_MAP () };  CAboutDlg:: CAboutDlg (): CDialog (CAboutDlg:: IDD)  {  }  void CAboutDlg:: DoDataExchange (CDataExchange* pDX)  {         CDialog:: DoDataExchange (pDX);  }  BEGIN_MESSAGE_MAP (CAboutDlg, CDialog)  END_MESSAGE_MAP ()  // CtestdllDlg dialog  CtestdllDlg:: CtestdllDlg (CWnd* pParent / * = NULL*/)        : CDialog (CtestdllDlg:: IDD, pParent)         , i1 (0)         , i2 (0)         , add2Edit (0)         , submul5Edit (0)  {         m_hIcon = AfxGetApp ()> LoadIcon (IDR_MAINFRAME);  }  void CtestdllDlg:: DoDataExchange (CDataExchange* pDX)  {         CDialog:: DoDataExchange (pDX);         DDX_Text (pDX, IDC_EDIT1, i1);         DDX_Text (pDX, IDC_EDIT2, i2);         DDX_Text (pDX, IDC_EDIT3, add2Edit);         DDX_Text (pDX, IDC_EDIT4, submul5Edit);  }  BEGIN_MESSAGE_MAP (CtestdllDlg, CDialog)         ON_WM_SYSCOMMAND ()         ON_WM_PAINT ()         ON_WM_QUERYDRAGICON ()         //}} AFX_MSG_MAP         ON_BN_CLICKED (IDC_BUTTON1, OnBnClickedButton1)  END_MESSAGE_MAP ()  // CtestdllDlg message handlers  BOOL CtestdllDlg:: OnInitDialog ()  {         CDialog:: OnInitDialog ();         // Add " About... " menu item to the system menu.         // IDM_ABOUTBOX must be in the system command range.         ASSERT ((IDM_ABOUTBOX and 0xFFF0) == IDM_ABOUTBOX);         ASSERT (IDM_ABOUTBOX <0xF000);         CMenu* pSysMenu = GetSystemMenu (FALSE);         if (pSysMenu! = NULL)         {              CString strAboutMenu;              strAboutMenu. LoadString (IDS_ABOUTBOX);              if (! strAboutMenu. IsEmpty ())              {                     pSysMenu-> AppendMenu (MF_SEPARATOR);                     pSysMenu-> AppendMenu (MF_STRING, IDM_ABOUTBOX,  strAboutMenu);  }  }  // Set the icon for this dialog. The framework does this automatically  // when the main application window is not a dialog.         SetIcon (m_hIcon, TRUE); // Set big icon         SetIcon (m_hIcon, FALSE); // Set small icon  // TODO: Add extra initialization here.         return TRUE; // Return TRUE unless you set the focus on a control.  }  void CtestdllDlg:: OnSysCommand (UINT nID, LPARAM lParam)  {   if ((nID and 0xFFF0) == IDM_ABOUTBOX)   {    CAboutDlg dlgAbout;    dlgAbout. DoModal ();  }  else   {  CDialog:: OnSysCommand (nID, lParam);  }  }  void CtestdllDlg:: OnPaint ()  {   if (IsIconic ())   {    CPaintDC dc (this); // Device context for painting  SendMessage (WM_ICONERASEBKGND, reinterpret_cast <WPARAM> (dc. GetSafeHdc ()), 0);    // Center icon in the client rectangle    int cxIcon = GetSystemMetrics (SM_CXICON);    int cyIcon = GetSystemMetrics (SM_CYICON);    CRect rect;    GetClientRect (*rect);    int x = (rect. Width ()   cxIcon + 1)/2;    int y = (rect. Height ()   cyIcon + 1)/2;    // Draw the icon    dc. DrawIcon (x, y, m_hIcon);  }    else    {    CDialog:: OnPaint ();  }  }  // The system calls this function to obtain the cursor to display  // while the user drags the minimized window.  HCURSOR CtestdllDlg:: OnQueryDragIcon ()  {   return static_cast <HCURSOR> (m_hIcon);  }  void CtestdllDlg:: OnBnClickedButton1 ()  {   // TODO: Add your control notification handler code here.   UpdateData (TRUE);   add2Edit = add2  (i1, i2);   submul5Edit = submul5 (i1, i2);   UpdateData (FALSE);  } 
image from book
 

Functions imported from DLL must be declared, which is shown on the following lines of the source code:

 int _ _declspec(dllimport) add2 (int i1, int i2);  int _ _declspec(dllimport) submul5 (int i1, int i2); 

We need to include the import library image from book  addsub.lib in the project and copy image from book  addsub.dll into the working directory.

The application window is shown in Fig. 8.3.

image from book
Fig. 8.3: Application window that demonstrates the use of the addsub.dll library

Until now, we considered load-time dynamic linking of DLL by means of import library. Another frequently used method is run-time dynamic linking of library while application runs. In this case, there is no need to link the application with an import library. For run-time dynamic linking of DLL, the LoadLibrary function is used. The function returns a descriptor of an instance, which refers to DLL. If an error occurs, NULL is returned. To use any function exported from DLL, it is necessary to call the GetProcAddress function with a library instance descriptor and the name of a function. The GetProcAddress function returns the pointer to the called function, or NULL if an error occurred.

After work with library is completed, remove it from memory by using the FreeLibrary function call.

To demonstrate the method of run-time dynamic linking, I will use the image from book  addsub.dll library developed before. The only thing you need is to develop the application in C++ .NET. The source code of the application is shown in Listing 8.10.

Listing 8.10: Demonstration of run-time linking of DLL
image from book
 // testsub2.cpp: Defines the entry point for the console application.  #include "stdafx.h"  #include <windows.h>  int _tmain (int argc, _TCHAR* argv [])  {         typedef UINT (*LPFNDLLFUNC) (UINT, UINT);         LPFNDLLFUNC add2,submul5;         HINSTANCE hDll = LoadLibrary ("addsub");         if (! hDll)         {          printf (" Unable to load library\n ");         getchar ();         exit (1);  }        add2 = (LPFNDLLFUNC) GetProcAddress (hDll, "add2");        submul5 = (LPFNDLLFUNC) GetProcAddress (hDll, "submul5");        if ((add2 == NULL)   (submul5 == NULL))           {               printf (" Unable to load functions! \n ");               FreeLibrary (hDll);               getchar ();               exit (1);  }        int i1 = 5;        int i2 = -3;        int ires = add2 (i1, i2);        printf (" add2(%d, %d) \t = %d\n ", i1, i2, ires);        ires = submul5 (i1, i2);        printf (" submul5 (%d,%d) = %d\n ", i1, i2, ires);        FreeLibrary (hDll);        getchar ();        return 0;  } 
image from book
 

Now we will analyze the source code. First of all, define the pointer to a function that takes two integer parameters, and then declare add2 and submul5 as such pointers. The declaration looks like this:

 typedef UINT (*LPFNDLLFUNC) (UINT, UINT);  LPFNDLLFUNC add2, submul5; 

The LoadLibrary function loads DLL into the memory, and after successful completion, returns a descriptor of the loaded module; otherwise , the result is set to 0 and the application terminates:

 HINSTANCE hDll = LoadLibrary ("addsub");  if (! hDll)  {    printf (" Unable to load library\n ");    getchar ();    exit (1); } 

After the library is loaded, the pointers on memory locations where the functions reside are to be stored:

 add2 = (LPFNDLLFUNC) GetProcAddress (hDll, "add2 ");  submul5 = (LPFNDLLFUNC) GetProcAddress (hDll, "submul5");  if ((add2 = NULL)   (submul5 = NULL))   {    printf (" Unable to load functions! \n ");    FreeLibrary (hDll);    getchar ();    exit (1);  } 

In the case of successful execution of this chunk of code, variables add2 and submul5 contain the start addresses of executive images. Operators

 int ires = add2 (i1, i2);  ires = submul5 (i1, i2); 

call the add2 and submul5 functions. After completing the execution, the current instance of DLL must be released through the call of a WIN API function ” FreeLibrary .

The working application window is shown in Fig. 8.4.

image from book
Fig. 8.4: Application window that shows dynamic loading of add2 and submul5 functions

We have considered an example of run-time dynamic linking of DLL, when the library was created using Application Wizard C++ .NET, and a separate object module with assembly functions included. However, DLLs written in MASM could be dynamically loaded at the application s run time. We ll develop in assembler a DLL that includes the add2 and sub2 functions, implementing addition and subtraction of two integers, respectively. The source code of assembly module is shown in Listing 8.11.

Listing 8.11: Source code of addsub2.dll
image from book
 ;--------------------addsub2.asm-------- .686  .model flat, C  option casemap: none  .code  LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD    mov EAX, 1    ret  LibMain endp  add2 proc    push EBP    mov  EBP, ESP    mov  EAX, [EBP+8]  ; i1    add  EAX, [EBP+12] ; +i2    pop  EBP    ret  add2 endp  sub2 proc    push EBP    mov  EBP, ESP    mov  EAX, [EBP+8]  ;  i1    sub  EAX, [EBP+12] ; -i2    pop  EBP    ret  sub2 endp  end LibMain 
image from book
 

The DEF file of exported functions (named as image from book  addsub2.def ) contains the following lines:

 LIBRARY addsub2  EXPORTS   add2   sub2 

The library image from book  addsub2.dll can be created while the sequence of commands will execute:

 @echo off  if exist addsub2.obj del addsub2.obj  if exist addsub2.dll del addsub2.dll  ml/c/coff addsub2.asm  Link/SUBSYSTEM:WINDOWS/DLL/DEF:addsub2.def addsub2.obj  dir addsub2.*  pause 

The source code of the console application (named as test_asmdyn ), which uses the functions from image from book  addsub2.dll , is shown in Listing 8.12.

Listing 8.12: The source code of application using addsub2.dll
image from book
 // TEST_ASMDYN.cpp: Defines the entry point for the console application.  #include "stdafx.h"  #include <windows.h>  int _tmain (int argc, _TCHAR* argv [])  {         typedef UINT (*LPFNDLLFUNC) (UINT, UINT);         LPFNDLLFUNC add2, sub2;         HINSTANCE hDll = LoadLibrary ("addsub2");         if (! hDll)         {           printf (" Unable to load library\n ");           getchar ();           exit (1);  }         add2 = (LPFNDLLFUNC) GetProcAddress (hDll, "add2 ");         sub2 = (LPFNDLLFUNC) GetProcAddress (hDll, "sub2 ");         if ((add2 == NULL)   (sub2 == NULL))         {          printf (" Unable to load functions! \n ");          FreeLibrary (hDll);          getchar ();          exit (1);  }          int i1 = 5;          int i2 = 13;          int ires = add2 (i1, i2);          printf (" add2 (%d, %d) \t = %d\n ", i1, i2, ires);          ires = sub2 (i1, i2);          printf (" sub2 (%d, %d) = %d\n ", i1, i2, ires);          FreeLibrary (hDll);          getchar ();          return 0;  } 
image from book
 

The last two listings illustrate the fact that run-time dynamic linking of DLL is very convenient and has two major advantages. First, when the required DLL is not available, an application using load-time dynamic linking simply terminates, while the run-time dynamic linking is able to respond to the error. Second, if the DLL code changes, an application that uses load-time dynamic linking may also terminate, while an application linked at run-time is only affected if the desired functions are absent in the DLL.

The window of the running application is shown in Fig. 8.5.

image from book
Fig. 8.5: Window of the appendix showing dynamic loading of functions from library, developed in assembly language
Note  

Using DLL written in the assembler (but it concerns any library written in C++)

By default, C++ .NET compiler uses the calling convention _cdecl . Keep this in mind while creating the DLL in the assembler and compile the modules with appropriate setting.

For example, if you specify the parameters of a command ret in the assembly module (bold font in Listing 8.13), the result can be rather unsuccessful .

Listing 8.13: Incorrect use of calling convention
image from book
 ;-------------------------addsub2.asm----------------- .686  .model flat, C  option casemap:none  .code  LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD     mov EAX, 1     ret  LibMain endp  add2 proc    push EBP    mov  EBP, ESP    mov  EAX, [EBP+8]  ;  i1    add  EAX, [EBP+12] ;  +i2    pop  EBP  ret 8  add2 endp 
image from book
 

MASM created the object module without errors, but making the call of function from the main program will lead the application to crash (Fig. 8.6).

image from book
Fig. 8.6: Abnormal termination of the program at non-observance of the calling convention

Of course, you can set the options of the C++ .NET compiler so that the use of calling conventions different from _cdecl will be possible. Keep in mind that it can make the debugging of an application more complicated. Therefore, if there are no special needs, it is easier to write a DLL code with default settings, accepted in C++ .NET.

Our overview of the use of the assembler in development of DLL is now complete. This analysis could of course be more in-depth , and some questions may inevitably arise. However, our intention is that the material in this chapter will help the reader to resolve difficult problems of development and optimization of DLL with assembler.



Visual C++ Optimization with Assembly Code
Visual C++ Optimization with Assembly Code
ISBN: 193176932X
EAN: 2147483647
Year: 2003
Pages: 50
Authors: Yury Magda

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net