The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: Gil on April 11, 2005, 05:46:38 PM

Title: Another C calling question
Post by: Gil on April 11, 2005, 05:46:38 PM
Hi Guys,

I am stuck with C++ calling ASM.

I got help from the VC guys how to declare it in C, for example:
extern "C" void myfunc(int x);

In the ASM I program myfunc as God intended:
myfunc   proc
. . . .
myfunc   endp

This works fine, however, this calling uses __cdecl, in which the caller has to pop the arguments off the stack, very inconvenient when programming in ASM.

To prevent C++ from popping the arguments one can use stdcall:
extern "C" void __stdcall myfunc(int x);

But now the linker doesn't find myfunc.

When I look at the assembler code that C++ generates when myfunc is called:
with __cdecl  it is called as: call _myfunc
with __stdcall it is called as: call _myfunc@4

I tried to modify the myfunc name in the ASM file but nothing worked.

What's your take?

I can't get answers in a C forum as diehard C programmers get chills when talking about ASM (or any other language) :tdown

Thanks,
Gil
Title: Re: Another C calling question
Post by: Vortex on April 11, 2005, 06:57:49 PM
Hi Gil,

Could you post all your source files to the board? Plus, what are your development tools?
Title: Re: Another C calling question
Post by: Gil on April 11, 2005, 07:25:42 PM
Hi again

Sorry for the omission.
I am using VC++ and MASM that come with visual studio 2003 .NET.
I compile all files from the IDE.
There are no compiling erros.

I didn't post any code because the problem is not related to a specific code, just naming convention and a linker that doesn't agree with me...........

Gil
Title: Re: Another C calling question
Post by: Gil on April 11, 2005, 07:37:20 PM
Eureka!

Sometimes posting a question helps you organize your own thoughts.
Since VC calls myfunc as _myfunc, then if it looks for _myfunc@xx I have to name it myfunc@xx
(xx is the number of bytes pushed on the stack)

End of problem.
Title: Re: Another C calling question
Post by: hitchhikr on April 11, 2005, 07:41:34 PM
It shouldn't be necessary to use such names be sure you assembled the .obj file containing the function with:

{code]
.model flat,stdcall

Title: Re: Another C calling question
Post by: Robert Collins on April 11, 2005, 10:07:13 PM
I have a question also about a C program calling a function in MASM.

How do you do it?

My assembly code must have a.....


start:
  '
  '
end start


If I put a 'invoke ExitProcess ,0' after the start statement then the MASM program exits immediately and my C program has no chance in calling 'myfunct'. If I omit the 'invoke ExitProcess, 0' then the assembly program terminates with an error.

If I put the function within the start.....end start statements like this:

  '
  '
.code

start:

myfunct proc
     invoke ShowMessageBox
     invoke ExitProcess,0
myfunct endp

END start

....then the assembly execution falls through into the 'myfunct' code.

I don't get it.

Title: Re: Another C calling question
Post by: Robert Collins on April 11, 2005, 10:31:23 PM
Quote from: Gil on April 11, 2005, 05:46:38 PM
.........extern "C" void __stdcall myfunc(int x);

Maybe you should omit the "C" part and just declare your external function as

extern void _stdcall myfunc(int x);

Then in your assembly code do as hitchhikr said... 

.model flat, stdcall




Title: Re: Another C calling question
Post by: GregL on April 11, 2005, 11:46:01 PM
Here's a good article on calling MASM procedures from C/C++:

http://www.developer.com/lang/article.php/3493531

Thanks to 'farrier' for posting the link.
Title: Re: Another C calling question
Post by: tenkey on April 12, 2005, 12:06:19 AM
Quote from: Robert Collins on April 11, 2005, 10:07:13 PM
I have a question also about a C program calling a function in MASM.

How do you do it?

My assembly code must have a.....


start:
  '
  '
end start


Not for static linking -- if you're starting from the C main() function. [Or a Windows WinMain() function.]
If you're starting from C or C++ code, eliminate the startup stuff from the ASM code.

For a DLL, the start function is a DllEntry or DllMain function.
Title: Re: Another C calling question
Post by: Robert Collins on April 12, 2005, 12:19:25 AM
Quote from: tenkey on April 12, 2005, 12:06:19 AM
Not for static linking -- if you're starting from the C main() function. [Or a Windows WinMain() function.]
If you're starting from C or C++ code, eliminate the startup stuff from the ASM code.

For a DLL, the start function is a DllEntry or DllMain function.

If I do that, like in the following snippit....


.486
.model flat, stdcall
option casemap :none

.code

TestProc proc dwValue:DWORD

   mov eax, dwValue
   add eax, 100
   ret

TestProc endp

end


I will get the following link errors...

LINK : error LNK2001: unresolved external symbol _WinMainCRTStartup
myasmprog.exe : fatal error LNK1120: 1 unresolved externals

I am not having a C problem, I am having an assembly problem if I omit the 'start: end start' statements.
Title: Re: Another C calling question
Post by: GregL on April 12, 2005, 01:26:32 AM
Are you using LINK /DLL ?
Title: Re: Another C calling question
Post by: Robert Collins on April 12, 2005, 01:36:10 AM
Quote from: Greg on April 12, 2005, 01:26:32 AM
Are you using LINK /DLL ?


No, it is not a DLL I am making in MASM. The snippit I posted was from that
http://www.developer.com/lang/article.php/3493531 link you posted earlier.

I already know how to call a function from an assemble DLL. I was just trying to make a simple function using MASM and then add the .obj to the 'C' program. I am not having any problems with the C program, just with the MASM program if I omit the start: end start statements and that is how it is shown in the sample from that above link.

Title: Re: Another C calling question
Post by: GregL on April 12, 2005, 01:51:21 AM
Robert,

Oh, I thought you were trying to make a DLL now, sorry.  :red

Just assemble the .asm file into an .obj file, don't link it. The error is from the linker looking for an entry point, the entry point is in the C program.

I was able to assemble the .asm file exactly as it is in the article:

.486
.model flat, stdcall
option casemap :none

.code

TestProc proc dwValue:DWORD

   mov eax, dwValue
   add eax, 100
   ret

TestProc endp

end


I had to make some small changes to the C program as follows (I'm using Pelle's C):

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

extern unsigned int __stdcall TestProc(unsigned int dwValue);

int main(void)
{
   unsigned int dwValue  = 100;
   unsigned int dwReturn = TestProc(dwValue);

   printf("%u\n", dwReturn);
   getchar();

   return 0;
}


It works.  :bg

Sorry for the C code hutch.

Title: Re: Another C calling question
Post by: hitchhikr on April 12, 2005, 04:29:52 AM
Quote
I will get the following link errors...

LINK : error LNK2001: unresolved external symbol _WinMainCRTStartup
myasmprog.exe : fatal error LNK1120: 1 unresolved externals

I am not having a C problem, I am having an assembly problem if I omit the 'start: end start' statements.

Use /c option in ml arguments line.
The above example is just perfect, use it as a base but just note that if you're using C++ compiler (like VC) you'll need to use this instead:


extern "C" unsigned int __stdcall TestProc(unsigned int dwValue);


to tell the compiler that TestProc is the real name of the function and to avoid the name mangling stuff (a c++ compiler would wait for a function called: TestProc@@YGII@Z).

Also in the "end blahblah" stuff "'blahblah" is just a label passed by masm to the linker to be used as an entrypoint (for an exe or a dll).
Title: Re: Another C calling question
Post by: hutch-- on April 12, 2005, 06:05:39 AM
 :bg

Greg,

Quote
Sorry for the C code hutch

We only get a little short on people who post their homework in C expecting others to translate it for them so they get their assignments done.
Title: Re: Another C calling question
Post by: Robert Collins on April 12, 2005, 01:03:54 PM
Quote from: hitchhikr on April 12, 2005, 04:29:52 AM
.....note that if you're using C++ compiler (like VC) you'll need to use this instead:


extern "C" unsigned int __stdcall TestProc(unsigned int dwValue);


to tell the compiler that TestProc is the real name of the function and to avoid the name mangling stuff (a c++ compiler would wait for a function called: TestProc@@YGII@Z).


I used 'C' instead of 'C++' so that syntax must be for 'C++' only because if I try that in 'C' I get an unresolved external reference so in plain 'C' I have to omit the "C" part and use just

extern unsigned int _stdcall TestProc(unsigned int dwValue);


Also, you don't need the double underscore, one underscore works fine.






Title: Re: Another C calling question
Post by: hitchhikr on April 12, 2005, 02:36:34 PM
C++ compilers can use both for backwards compatibility purposes, they usually switch to C mode whenever they're compiling a .c file and C++ mode with .cpp files.

_stdcall is just a convenient macro, the real one is __stdcall (just disable the language extensions in VC and try to compile a _stdcall function in a .c or .cpp file).
Title: Re: Another C calling question
Post by: Robert Collins on April 12, 2005, 04:51:38 PM
Out of curiosity, can Visual Basic also call a function from assembly? I know it can if the assembly code is a DLL but I mean in the same sense as the above C code called the assembly function.
Title: Re: Another C calling question
Post by: hitchhikr on April 12, 2005, 05:07:06 PM
VB uses stdcall, theorically it can since it uses ms link to create executables.

I never tried but if i had a guess i'd say that it would probably require some hacks like the modification of the vb executable that launches the linker in order to inject the .obj files into it's command line (most probably by launching a wrapper tool instead of link.exe).

I don't know about vb.net.
Title: Re: Another C calling question
Post by: Robert Collins on April 12, 2005, 05:21:22 PM
Ummm......I have an example of a Visual Basic program that calls a Java Class function so maybe somewhere along that same line one can use that approach to also call a MASM function or even a C function for all that matters.
Title: Re: Another C calling question
Post by: pbrennick on April 12, 2005, 07:52:46 PM
Hi Robert,
That seems to be the case.  Since Java compiles to byte code it is very similar to an asm object.  I stopped using Visual Basic a while ago, version 3 was the last that I used.  Version 3 did not create a standard 32 bit executable (PE) even though it created a windows program, so I must assume that it does so now.  Bieb would probably be the one to ask about that one...

Paul