I have a few questions with creating & using DLLs, MAMS, & C/C++.

1.) Once I've created a DLL, with external functions, how can I use it with MASM? 

  Do I use "LoadLibrary" & then the function name is loaded for me to pass arguments to?

2.) Is there any advantage to creating a DLL in MASM over creating it in C/C++ (or vise versa)?

Thank you,
-#2pencil-
Posted on 2005-09-23 12:41:30 by number2pencil
1) You can build an import library and then call the function like how you do for normal win32api. Just remember to declare the prototypes.

2) If you are a good coder, the code will be faster. There is always a high chance that the dll coded in masm will be smaller than those coded in C/C++ (especially C++ I think).
Posted on 2005-09-23 12:57:56 by roticv

2.) Is there any advantage to creating a DLL in MASM over creating it in C/C++ (or vise versa)?

Depends on your skills in assembly and C/C++.
Use whatever language you're most familiar with, and you'll be fine. If you feel that C/C++ is "too large", you can easily stop including the runtimes if you don't use them anyway - or take a look at Jibz' WCRT - http://www.ibsensoftware.com
Posted on 2005-09-23 13:50:20 by f0dder
What am I doing wrong here?


;out_dll.inc
include \masm32\include\windows.inc
includelib \masm32\lib\kernel32.lib  ; you need this one for sure.
includelib \masm32\lib\user32.lib  ; if necessary ... usually it is.

PUBLIC YourFunc
YourFunc PROTO arg1:DWORD, arg2:DWORD



;out.asm
.586P
.model flat,stdcall
option casemap:none

;#################################
include out_dll.inc
;#################################

.DATA

.CODE

start:
;#################################
DllStart PROC  hInstDLL:DWORD,dwNotify:DWORD,lpReserved:DWORD
;#################################
        mov    eax,dwNotify
        cmp eax,01h ;DLL_PROCESS_ATTACH
        je @@01
        cmp eax,02h ;DLL_THREAD_ATTACH
        je @@02
        cmp eax,03h ;DLL_THREAD_DETACH
        je @@03
        cmp eax,00h ;DLL_PROCESS_DETACH
        je @@exit
@@01:
nop
        jmp @@out
@@02:
nop ; thread-specific code
jmp @@out
@@03:
nop ;thread-specific cleanup code
jmp @@out
@@exit:
nop    ;general cleanup code
jmp @@out
@@out:
mov eax, 1
ret  12
DllStart ENDP

YourFunc PROC arg1:DWORD, arg2:DWORD

YourFunc ENDP
END start
end
;#################################



#include <windows.h>
#include <stdio.h>

typedef UINT (CALLBACK* LPFNDLLFUNC1)(VOID);

HINSTANCE hDLL;             
LPFNDLLFUNC1 YourFunc;   
UINT  uReturnVal;

int main() {
hDLL = LoadLibrary("out.dll");

if(hDLL){
YourFunc = (LPFNDLLFUNC1)GetProcAddress(hDLL,"YourFunc");
  if (!YourFunc){ // || !MyFunc2){
printf("Function address not found in DLL");
FreeLibrary(hDLL);     
return false;
}
else{
printf("done");
YourFunc();
}
}
else printf("DLL failed to load");
return true;
}


If I leave ret 12 in, it crashes after it prints done.  If it take ret 12 out, it "fails to load".  What causes this, & what have I overlooked?

Thank you,
-#2pencil-


C:\DOCUME~1\user\asm> ml  /c  /coff  /Cx out.asm /Fo out.obj
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: out.asm

C:\DOCUME~1\user\asm>C:\masm32\bin\link /DLL /SUBSYSTEM:WINDOWS /entry:DllStar
t /DEF:out.def  /LIBPATH:c:\masm\lib out.obj
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

  Creating library out.lib and object out.exp
Posted on 2005-09-23 14:47:55 by number2pencil
Since you have ".model flat,stdcall", and aren't specifying calling convention, your function is STDCALL by default (you really ought to explicitly tell that it's STDCALL, it looks better).

Anyway, "ret" is a macro, and "ret xx" emits the "ret xx" directly. Use "ret", it will add the "12" itself, and also tear down the stack frame.

Geez my english sucks right now :)
Posted on 2005-09-23 16:36:39 by f0dder
Pencil,

This is the minimum you need to get a DLL entry procedure working.


LibMain:
    mov eax, 1
    ret 12

  ; all of your code inbetween

end LibMain


The linker will display a warning about the calling convention and argument byte count if you don't use a procedure but it works fine. For a simple startup of a DLL the following code will do the job fine.


LibMain proc instance:DWORD,reason:DWORD,unused:DWORD

    .if reason == DLL_PROCESS_ATTACH
      mov eax, TRUE

    .elseif reason == DLL_PROCESS_DETACH

    .elseif reason == DLL_THREAD_ATTACH

    .elseif reason == DLL_THREAD_DETACH

    .endif

    ret

LibMain endp


This will give you direct mnemonic code as follows.


  start:
    push ebp
    mov ebp, esp

    cmp DWORD PTR , 1
    jnz lbl0
    mov eax, 1
    jmp lbl3

  lbl0:
    cmp DWORD PTR , 0
    jnz lbl1
    jmp lbl3

  lbl1:
    cmp DWORD PTR , 2
    jnz lbl2
    jmp lbl3

  lbl2:
    cmp DWORD PTR , 3
    jnz lbl3

  lbl3:
    leave
    ret 0Ch


Regards,

hutch at movsd dot com
Posted on 2005-09-23 19:32:58 by hutch--