Hi Guys,
Very rusty here with ASM, so please bear with me. :biggrin:
I'm encountering a problem attempting to make a static lib file and getting it to work in a MS Visual Studio C/C++ project.
Just doing a simple function at this stage to add two numbers.
.486
.model flat, stdcall
.code
start:
addnums proc num1:dword, num2:dword
mov eax, num1
mov ecx, num2
add eax, ecx
ret
addnums endp
end start
It seems to compile and link happily if I do the following and generates an 'addnums.lib' file.
ml.exe /c /coff addnums.asm
link /NOLOGO /SUBSYSTEM:CONSOLE /out:addnums.lib addnums.obj
But if I attempt to use the generated lib file in my C/C++ project it says "Warning LNK4003 - invalid library format; library ignored"
Any ideas on what I might be missing here would be greatly appreciated. :thumbsup:
I thought you would use LIB, not LINK?
VS might expect the procedure name to be "decorated" too.
Hi Sinsi, thanks for the reply.
I was just about to post, I got it 'recognised' by VS by using Polib and no longer get that error. However, I am now getting other errors.
Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol _addnums
Error LNK1120 4 unresolved externals
Error LNK2001 unresolved external symbol __imp__system
Error LNK2001 unresolved external symbol ___CxxFrameHandler3
Error LNK2001 unresolved external symbol ___std_terminate
I suspect that the first one is due to the naming decorations that you just mentioned. How does one go about 'decorating' the names?
Many thanks, once again.
Scratch the above post, I've now got the error down to being unable to find the function
Error LNK2001 unresolved external symbol _addnums
Happening whether I do this "extern "C" double addnums(double a, double b)" or "extern "C" double _addnums(double a, double b)"
This is my main project as it stands now. The asm code is still the same as in the initial post.
#include <iostream>
#pragma comment(lib, "R:/Programming Archive/Source/asm/bin/addnums.lib")
extern "C" double addnums(double a, double b);
//double _addnums(double a, double b);
int main()
{
std::cout << addnums(2,3);
system("PAUSE");
}
These two conflict
.model flat, stdcall
extern "C" double addnums(double a, double b)
The ASM code expects integers but the C code is for doubles...
No idea about C/C++ but if you get the calling convention right I assume that the linker would decorate the export name properly.
Ah, right you are! I mistakenly took DWORD as being a double, where it should be an int and have corrected that part of the code.
extern "C" int addnums(int a, int b);
int main()
{
std::cout << addnums(2,3);
system("PAUSE");
}
Still unfortunately having grief with the linker though.
Error LNK2001 unresolved external symbol _addnums
It's still insisting that it cant find _addnums (with an underscore). :undecided:
Dumpbin.exe seems to show that the exported lib has the function in there happily.
2 public symbols
1 _addnums@8
1 _start
I know SFA about C/C++ but found this
extern "C" int __stdcall addnums(int x,int y)
This also assumes you are building a 32-bit app.
That's about as far as I can go since the library seems correct :thumbsup:
Thanks Sinsi, I was just replying as your post popped up.
I got it going, but geez, I had to jump through some hoops with Visual Studio.
I had to do the following,
Configuration properties > Calling Convention > __stdcall (/Gz)
Configuration properties > Linker > Advanced > Image Has Safe Exception Handlers - No (/SAFESEH:NO)
Don't know if what I have done there is a bad thing or what? :badgrin:
I guess if anything else, it gives me a playing field when I can test out what I'm trying to do. Can work out the finer details later on. Haha!
Many thanks for your assistance, Sinsi :thumbsup:
Can you do me a favour? Revert to the original configuration options and try that declaration?
I'm curious to see if that fixed it.
It seems to me that forcing an entire C program to use stdcall is...excessive :badgrin:
"extern C" but not "addnums proc C, arg:dword, arg2:dword"
Is that legit?
Shouldn't the procedure be c as well? Looks weird, so I ask..
Btw, seems it would be way easier just to use a batch file. No interference from VS that way. :tongue: You can then write the command line arguments exactly as you need them, not as VS thinks they should be.
AddNums.asm:
.486
.model flat, stdcall
.code
include AddNums.inc
;------------------------------------------------------------------------------
; Add two integers together and returns the result
;------------------------------------------------------------------------------
AddIntegers PROC Num1:DWORD, Num2:DWORD
mov eax, Num1
add eax, Num2
ret
AddIntegers ENDP
END
No need to add END start, just add END for your library in the main file. You can also include other files, other .asm modules or .inc files to help with organizing everything.
AddNums.inc:
;==============================================================================
;
; AddNums Library
;
;==============================================================================
AddIntegers PROTO Num1:DWORD, Num2:DWORD
The AddNums.inc is an include file for assembler users.
For c/cpp users you can create an header file for them:
AddNums.h:
/*=============================================================================
AddNums Library
=============================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER // MSVC compiler
#define APIEXPORT __declspec(dllexport) __stdcall
#else
#define APIEXPORT
#endif
int APIEXPORT AddIntegers(int Num1, int Num2);
#ifdef __cplusplus
}
#endif
You can then copy the AddNums.lib and AddNums.h to your visual studio solution to compile the test console program:
AddNumbers.cpp:
#include <iostream>
#include <AddNums.h>
#pragma comment(lib, "AddNums.lib")
int main()
{
std::cout << AddIntegers(2, 3) << std::endl;
system("PAUSE");
}
I added AddNums.h to the header files section in the solution. Other settings I modified in the test program (AddNumbers.exe) in the visual studio solution are for Release (x86) Win32:
Advanced->Character Set: Not Set
Advanced->Whole Program Optimization: No Whole Program Optimization
VC++ Directories->Include Directories: <Add this projects folder to this so that it will pick up the AddNums.h that you copied here.>
C/C++->General->Debug Information Format: None
C/C++->Code Generation->Enable C++ Exceptions: No
C/C++->Code Generation->Runtime Library: Multi-threaded (/MT)
C/C++->Code Generation->Security Check: Disable Security Check (/GS-)
Linker->Debugging->Generate Debug Info: No
Linker->Advanced->Randomized Base Address: No (/DYNAMICBASE:NO)
Linker->Image Has Safe Exception Handlers: No (/SAFESEH:NO)
Wowza. Heaps of replies in here now. Many thanks, everyone.
@fearless - Yeah, I ended up removing the references to 'start'. Dumpbin, bought that to my attention when it was showing up as an exported function.
Lots of suggestions here for my to try out though. I haven't attempted to mix Asm generated libs with a C/C++ project before, so I'm certainly open to any suggestions. :biggrin:
Quote from: zedd151 on November 06, 2024, 02:29:49 PMBtw, seems it would be way easier just to use a batch file. No interference from VS that way.
Yabbut, it looks like they're using Visual Studio because they have a C/C++ project they want to link it to. So using a batch file probably isn't an option.
Quote from: NoCforMe on November 06, 2024, 03:25:11 PMYabbut, it looks like they're using Visual Studio because they have a C/C++ project they want to link it to. So using a batch file probably isn't an option.
I somehow missed that part, thanks.
Quote from: NoCforMe on November 06, 2024, 03:25:11 PMYabbut, it looks like they're using Visual Studio because they have a C/C++ project they want to link it to. So using a batch file probably isn't an option.
Yeah, batch file is an
option but I'd rather not add more relative unknowns where I can. At the moment the project is workable and I can play around with it. Can fine tune the setup more later on as I go.