This question is mainly for Vortex.
The other day you gave me an example of making a DLL and using it in an Assembly language program. After looking over it for awhile I finally got the hang of it up to a point. The part of assembling the program, using the 'Build.bat' file was really straight forward and works without any problems as long as I put the include statement in the source code and have the 'mydll2.dll' file and the 'mydll2.lib' file available. However, I am still a little vague about the making of the DLL and the .Lib file. If I run the 'BuildDLL.bat' file I get the correct DLL and .LIB file as output and that is what I use when I assemble the program. I see that in order to run the 'BuildDLL.bat' I have to have the 'MyDLL2.Obj' and the 'MyDLL2.def' file as input. My question is how did you get the 'MyDLL2.OBJ file. I know that it must be the output of the Assembler so I tried using the 'MyDll2.c' program and the 'MyDLL2.def' file and recompile it using MS VC++. I got a link error but was able to correct it so I did get a .OBJ file from the compilation of 'MyDLL2.c'. I used this .OBJ as the input to 'BuildDLL.bat but it didnt work. So, I figured it then must be the output of assembling the 'MyDLL2.ASM' file using MASM. When I tried to do that I got an error from MASM about the 'include listing.inc' statement because that file is missing from the sample you gave me. The other question I have is how did you make the 'MyDLL2.ASM' file? If you made it from scratch then I am completely lost since I would have no idea how to make one myself if I needed to make another DLL. It looks though as if it was made by parsing the original file I made and converting it to an assembly source code. If this is the case then what did you use to get the .ASM file results?
Hope you can help me with this but thanks anyway for what you already have done.
win32asm.cjb.net (http://win32asm.cjb.net)
Read the Turor by Iczelion- Tutorial 17: Dynamic Link Libraries
- Tutorial 26: Splash Screen
Then you do something what you want to do at making and using a DLL with Assembly language program
regards
Robert,
Two things to watch out for between C and MASM, make sure the calling conventions are the same in the way you prototype them and check the compiler syntax for EXTERN C so you don't get any name mangling. A DLL created in MASM should be fine with Microsoft C.
Hi Robert,
Yes, you are right about mydll2.asm. If you examine build.bat, you will see that the first line of batch file launches Cl.exe , the Visual C++ compiler. One of the switches of cl.exe is aimed to output (/FAs) an assembly listing of the original C source file. This listing helps me to understand how the compiler deals with the source file at low level. When I will be back home, I will provide you more information about building the DLL.
Hi Robert,
To make it clearer, I removed the options generating the assembly listing file mydll2.asm, you can check the attachment.
[attachment deleted by admin]
Quote from: six_L1 on December 20, 2004, 05:20:39 AM
win32asm.cjb.net (http://win32asm.cjb.net)
Read the Turor by Iczelion
- Tutorial 17: Dynamic Link Libraries
- Tutorial 26: Splash Screen
Then you do something what you want to do at making and using a DLL with Assembly language program
regards
Where is Tutorial 26? I downloaded Steve's 'masm32' but it only goes up to Tutorial 24 and also Tutorial 01 is missing.
Also, the example in Tutorial 17 is fine if one is creating a DLL in Assembly language but I have to create the DLL using MS VC++ (boss's orders) and that is where I am have a problem getting the DLL to work in an Assembly program.
You can get any of the missing tutorials from here:
http://win32asm.cjb.net/
Just click the link for tutorials.
Quote from: Robert Collins on December 20, 2004, 08:48:06 PM
[...]
Also, the example in Tutorial 17 is fine if one is creating a DLL in Assembly language but I have to create the DLL using MS VC++ (boss's orders) and that is where I am have a problem getting the DLL to work in an Assembly program.
What part are you having trouble with?
The BuildDLL.bat file will build the C dll from the Mydll2.c source code. The Msgbox.asm file then will use that dll.
In an effort to simplify things for you I have removed anything that is not strictly necessary to build this and uploaded it here as a zip file.
Make sure the c compiler (cl.exe) and linker (link.exe) are on your path and then simply execute builddll.bat to build the dll. Then execute build.bat to build the asm app that uses the dll you just created. When you execute the resulting executable (Msgbox.exe) you will see that it executes a procedure in the C dll.
I hope this helps clear it up for you.
[attachment deleted by admin]
Quote from: John on December 20, 2004, 08:55:06 PM
You can get any of the missing tutorials from here:
http://win32asm.cjb.net/
Just click the link for tutorials.
Thanks for the link, John. That's a pretty cool Web Site.
Quote from: John on December 20, 2004, 09:01:49 PM
Quote from: Robert Collins on December 20, 2004, 08:48:06 PM
[...]
Also, the example in Tutorial 17 is fine if one is creating a DLL in Assembly language but I have to create the DLL using MS VC++ (boss's orders) and that is where I am have a problem getting the DLL to work in an Assembly program.
What part are you having trouble with?
The BuildDLL.bat file will build the C dll from the Mydll2.c source code. The Msgbox.asm file then will use that dll.
The original problem (now because of you and Vortex, I'm not sure it's a problem anymore) was that I had to take a DLL that was written by the Systems Programming Dept where I work and use it in an Assembly application that has been assigned to me. All DLLs are written in MS VC++ (no exceptions). These DLLs are used by the company in all applications written by the Applications Programming Dept (which I am part of) and they all work when used in other programs written in VB, C/C++, VJ++ 6.0, Delphi, etc. except I have been unsuccessful in getting them to work in an Assembly program. The DLLs are valid but I guess I am doing something wrong in trying to get them to work because during the assembling of the program I always get an unresolved external reference during the linking. Either the problem lies in the .LIB file or it's me. I'm begining to think that there is no way to use the DLLs as they are given to me in an Assembly program. However, I can take the DLL (that is, its C++ source -->MyDLL.cpp, for example) and use it as input to the BuildDLL.BAT file and this creates a DLL and a LIB file that does work. Now, I have to convince the Systems Programming Dept that they are going to have to run their DLL source programs through the BuildDLL.bat but because of strict company policies I'm not sure they will agree. If there is a way to use the DLLs as written then I have to find the answer to how to use them in Assembly but if it can't be done then the only choise left is what you gave me in the VCDLL.ZIP file.
I thought it was said earlier but I'm not sure. I believe the problem you are having is caused by the fact that you don't have the .LIB file for the DLL. The lib file will be generated by the C compiler (cl.exe) when it is run, as demonstrated here. You will need this when you build your ASM app.
Can't you just ask them to either recompile the dll and give you the lib file or ask them for the lib file provided they are saved? Far as I know, admittedly not much, you can't do anything without it.
Quote from: John on December 21, 2004, 01:28:36 AM
I thought it was said earlier but I'm not sure. I believe the problem you are having is caused by the fact that you don't have the .LIB file for the DLL. The lib file will be generated by the C compiler (cl.exe) when it is run, as demonstrated here. You will need this when you build your ASM app.
Can't you just ask them to either recompile the dll and give you the lib file or ask them for the lib file provided they are saved? Far as I know, admittedly not much, you can't do anything without it.
No, that is and was not the problem. I always had both the .DLL file and the .LIB file. The problem is that when I assemble and link the 'MessageBox.asm' I get a link error saying 'unresolved external ShowMessageBox@0'. Either I am not doing the source code incorrectly or the linker cannot read a .LIB file from VC++. I think it's the .LIB file becaise VC++ outputs both the DLL and the LIB files but they are probably not in the correct format that the linker expects or something.
As far as dealing with the Systems Programming Dept is that they are bound by company policies and have to create all DLLs using MS VC++. They probably cant or wont give me the source code so I can use it as input to the BuildDLL.bat file. (P.S. I have never worked for a company that makes it easy for programmers to get their stuff done. Always some piss-ass policy that says you can't do this and you can't do that). Anyway, the problem still exists untill I find a way to use their DLLs or I convince the manager of programming that in order to use their DLLS I have to or they have to run them through the BuildDLL.bat file and create another DLL and LIB that works with assembly. Now, you see, the company would have to maintain two versions of the same DLL, one for all the other applications and one for the assembly programs. I don't think they want to do that.
Out of curiosity, what calling convention is being used in the dl and the ASM app?
[edit]/me takes note that hutch-- mentioned this in the beginning[/edit]
Quote from: John on December 21, 2004, 02:59:03 AM
Out of curiosity, what calling convention is being used in the dl and the ASM app?
[edit]/me takes note that hutch-- mentioned this in the beginning[/edit]
Here's the files I am using.......Note: The below C DLL is C++, not C. I think the #include "stdafx.h" statement is what makes it a C++ instead of a regular C program but that is what the System Programming Dept uses so I have to use C++ too.
Source for MyDLL2.cpp and MyDll2.def files
#include <windows.h>
#include "stdafx.h"
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
void _stdcall ShowMessageBox()
{
MessageBox (0,"HELLO FROM DLL","MYDLL.DLL",MB_OK);
return;
}
;mydll2.def
LIBRARY mydll2
EXPORTS
ShowMessageBox
Source for the MessageBox.asm file
.386
.model flat, stdcall
option casemap:none
ShowMessageBox PROTO
ExitProcess PROTO :DWORD
includelib \masm32\include\user32.lib
includelib \masm32\include\kernel32.lib
includelib mydll2.lib
.data
adr_MsgBox DD ShowMessageBox
adr_ExitProcess DD ExitProcess
.code
start:
call Do_MessageBox
push 0
call Do_Exit
;---------------------------------------------------------------------------
;
;----------------------------------------------------------------------------
Do_MessageBox:
jmp dword ptr ds:[adr_MsgBox]
Do_Exit:
jmp dword ptr ds:[adr_ExitProcess] ;Invoke the ExitProcess function
end start
Someone told me, not sure who it was, probably Hutch, that C++ uses a name mangleing technique and this is what I think is making the .LIB file
unreadable by the MASM Linker.
Now, when I assemble and link the above .asm I always get that 'unresolved external 'ShowMessageBox@0' message.
If the DLL was created using MS VC++ as a '.c' program(instead of a .cpp) and the #include stdafx.h statement removed then the output MyDLL2.dll and MyDLL2.lib files will work as is in the above Assembly program but not if the DLL is compiled as a C++ program. But the problem remains that the programmers in the System Programming are always going to make DLLs using .cpp files and not .c files. So, tha't my situation.
What is command line you use to assemble the ASM portion?
Make sure you are using the /Cx and /Cp options.
Also, why not use the invoke syntax, is that another restriction?
I've never seen it done the way you are doing it, but I'm pretty new to all of this anyway :red
Quote from: Robert Collins on December 21, 2004, 04:00:55 AM
void _stdcall ShowMessageBox()
{
MessageBox (0,"HELLO FROM DLL","MYDLL.DLL",MB_OK);
return;
}
... snip ...
Now, when I assemble and link the above .asm I always get that 'unresolved external 'ShowMessageBox@0' message.
If the DLL was created using MS VC++ as a '.c' program(instead of a .cpp) and the #include stdafx.h statement removed then the output MyDLL2.dll and MyDLL2.lib files will work as is in the above Assembly program but not if the DLL is compiled as a C++ program. But the problem remains that the programmers in the System Programming are always going to make DLLs using .cpp files and not .c files. So, tha't my situation.
In VC++, you need to add
extern "C".
extern "C" void _stdcall ShowMessageBox()
{
MessageBox (0,"HELLO FROM DLL","MYDLL.DLL",MB_OK);
return;
}
If you have examples of the DLL's or its functions' declarations and uses in VB 6, it will be more revealing. You only need to supply one function that has arguments.
Quote from: tenkey on December 21, 2004, 07:33:43 AM
In VC++, you need to add extern "C".
extern "C" void _stdcall ShowMessageBox()
{
MessageBox (0,"HELLO FROM DLL","MYDLL.DLL",MB_OK);
return;
}
.
Damn! You know I tried that the other day but instead of putting the extern "C" as part of the function I put it at the top of the file thinking that's where it should be so that it would be global for all functions, but it didn't work so I just abandoned that thought. It didn't occur to me to put it in the function. Thanks, tenkey, that solves my problem.
The other thing you can do to make sure you have "extern 'c'" prototype for all your .asm functions which are called from VC++ is create a header file with something like the following:
// make all functions standard "C" names and not C++ mangled.
#ifdef __cplusplus
extern "C"
{
#endif
// prototype goes here
void MyFunc();
void MyFuncWithArg(int argc);
/* etc, etc, etc */
// end specific C names
#ifdef __cplusplus
}
#endif
Then anytime you need to use one of your ASM functions, just include the appropriate header file (where you have the function declared).
Relvinian
OK, guys, thanks to each and everyone of you I can now sleep. I convinced the Systems Programming Dept, those who make the DLLs in VC++, to include a .h file as indicated above by Relvinian. This will solve the problem for all DLLs this day forward but not so for all them that have already been written. I suppose that if the company wants to develop certain applications in Assembly then someone is just going to have to go back and re-compile the older DLLs. Probably on a need to do basis.
Anyway, that's their problem.
Thanks to all for your help.
Hi Robert,
Did you check my second example? ( the new attachment )
help me
i'm created 2 files :
- file DLL
- file LIB
i create by MASM32
how to use it in the C++
i'm using dev-c++ thank
file cong.asm
==============================
cong proc a:DWORD
mov eax,a
inc eax
ret
cong endp
==============================
file cong.def
==============================
LIBRARY cong
EXPORTS cong
==============================
file CPP
===========================
DLLIMPORT int cong(int);
int main(void)
{
int a=10,b;
b=cong(a);
}
===========================
link error
lib file?
how you created?
this way?
rc.exe UtillMasm.rc
ml.exe /c /coff UtillMasm.asm
lib.exe /subsystem:windows UtillMasm.obj
###
or that way?
Quotei'm using dev-c++ thank
Are you referring to Bloodshed Dev-C++ ?
oh my fo!
c++ guy!
:toothy
help me
i need use masm32 to create file KIDTEAMDLL.DLL
after using in Dev-C++
code
file KIDTEAMDLL.ASM
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
; -------------------------------------------
; Build this DLL with the provided MAKEIT.BAT
; -------------------------------------------
.data?
hInstance dd ?
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
LibMain proc instance:DWORD,reason:DWORD,unused:DWORD
.if reason == DLL_PROCESS_ATTACH
mrm hInstance, instance ; copy local to global
mov eax, TRUE ; return TRUE so DLL will start
.elseif reason == DLL_PROCESS_DETACH
.elseif reason == DLL_THREAD_ATTACH
.elseif reason == DLL_THREAD_DETACH
.endif
ret
LibMain endp
kidteam proto
kidteam proc
jmp qua
nd BYTE "Ngo Hung Cuong",0
td BYTE "Kidteam",0
qua:
invoke MessageBox,0,addr nd,addr td,MB_OK
ret
kidteam endp
end LibMain
============================================
file makeit.bat
@echo off
if exist kidteamdll.obj del kidteamdll.obj
if exist kidteamdll.dll del kidteamdll.dll
\masm32\bin\ml /c /coff kidteamdll.asm
\masm32\bin\Link /SUBSYSTEM:WINDOWS /DLL /DEF:kidteamdll.def kidteamdll.obj
del kidteamdll.obj
del kidteamdll.exp
dir kidteamdll.*
pause
====================================================
file KIDTEAMDLL.DEF
LIBRARY kidteamdll
; EXPORTS [your_exported_proc_name]
EXPORTS kidteam
=====================================================
file testDLL.CPP
#include <windows.h>
#define DllImport extern "C" __declspec (dllimport)
DllImport void kidteam(void);
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
kidteam();
return 0;
}
but compiler error
[Linker error] undefined reference to `_imp__kidteam'
For MASM to recognise an external procedure you need to prototype it in MASM format taking notice of the calling convention you use.
kidteam,
It looks like you are trying to create a DLL with MASM and use it from a CPP app. Your makeit.bat should be creating the import library kidteamdll.lib. You need to link this import library with your test app.
default calling convention for masm32 is stdcall (as per "masm32rt.inc" ".module flat,stdcall")
default calling convention for any cpp compiler is cdecl
cdecl != stdcall
solution 1
kidteam proc c
solution 2
extern "C" __declspec (dllimport) void __stdcall kidteam(void);
use either "solution 1" or "solution 2", not both.
thanhk you very much