Calling C++ functions from MASM

Started by Vortex, August 26, 2006, 10:12:08 AM

Previous topic - Next topic

Vortex

Here is a simple example of calling a decorated C++ function from MASM.  The problem with C++ functions is that they have a complicated decoration scheme. An easy way to solve the problem is to look at the assembly listing produced by the C++ compiler. Of course, you can use a tool like dumpbin to view the decorated symbols :

\masm32\bin\dumpbin /SYMBOLS sum.obj

Microsoft (R) COFF Binary File Dumper Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.


Dump of file sum.obj

File Type: COFF OBJECT

.
.
008 00000000 SECT3  notype ()    External     | ?sum@@YGHHH@Z (int __stdcall sum(int,int))
.
.

The example project :

.386
.model flat, stdcall
option casemap :none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\user32.inc
include     \masm32\include\masm32.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\user32.lib
includelib  \masm32\lib\masm32.lib

?sum@@YGHHH@Z PROTO SYSCALL

sum EQU <pr2 PTR ?sum@@YGHHH@Z>


.data
format1 db  '10 + 20 = %d',0
x       dd  10
y       dd  20

.data?
buffer  db  100 dup(?)

.code

start:

    invoke  sum,x,y
    invoke  wsprintf,ADDR buffer,ADDR format1,eax
    invoke  StdOut,ADDR buffer
    invoke  ExitProcess,0

END start


Sum.cpp ( C++ source file compiled with VC++ Express 2005 ) :


int __stdcall sum(int x , int y)
{
  return(x+y);
}


Building the project :

cl /c /Oty2 /Zl /Gs /GS- /FoSum.obj /Fa Sum.cpp
\masm32\bin\ml /c /coff Sumtest.asm
\masm32\bin\polink /SUBSYSTEM:CONSOLE Sumtest.obj Sum.obj

[attachment deleted by admin]

ToutEnMasm

Hello,
Dumpbin is certainly useful for other purpose.
Protolib give (in comment) the Full translation of the decorated name.Including the type of call and the parameters.That is more useful to call a function.
                                      ToutEnMasm

               

Vortex

ToutEnMasm,

The problem here is not to undecorate a function but to find the decorated form as you need to write the prototype correctly so you can call the C++ function from your asm module :

?sum@@YGHHH@Z PROTO SYSCALL

GregL

Vortex,

Thanks for this good information.  :U  I had never mixed MASM and C++ before, I had only mixed MASM with C.

Why PROTO SYSCALL? I wouldn't have thought it was that.


GregL

Vortex,

I fiddled around with your example this evening. It got it to work including the C Run-Time Library <stdio.h> on the C++ side, but as soon as I included the C++ Standard Library <iostream> on the C++ side, things really got to be a mess. I never did get it to work.  :dazzled:  I got it to build but it would crash on execution. It's crashing in 'ostream'.


zooba

You can also use the extern "C" directive to export undecorated names.


Greg,

C++ uses special syntax for streams, perhaps this is causing issues. I don't actually have an installation of C++ here so I can't check.

Cheers,

Zooba :U

Vortex

Hi Greg,

Normally, the PROTO statement puts a leading underscore to the external functions. This is valid for STDCALL and C functions as they are decorated with a leading underscore : _ExitProcess@4

In our case, ?sum@@YGHHH@Z is exported without the underscore. So, to avoid the symbol appearing in the front of the function, we use the SYSCALL convention.

Looking at the assembly output of the compiler , sum.asm :

.model flat

.
.

PUBLIC ?sum@@YGHHH@Z

.
.


Zooba is right here, the special syntax of C++ can cause some errors. Greg, can you send your project here?

GregL

Vortex,

Thanks for the explanation.

Attached is the project after I modified it. I was using ML 6.15, VC++ 6.0 and MS Link 6.0.


zooba,

Thanks for the tip.



[attachment deleted by admin]

Vortex

Hi Greg,

Thanks for the example but it crashes on my Win XP HE SP2   Is there way to rebuild it with VC++ Express 2005?

GregL

Vortex,

Sure, I will make a copy of the project and switch to ML 8.0, VC++ 2005 and MS Link 8.0. I'll attach it when I'm done.

later:
It doesn't crash, it just gracefully exits. I get the same acess violation in the same spot in the debugger.



[attachment deleted by admin]

drizz

entrypoint is in asm code (main), hence the crt startup code is excluded,
hence the funcions that depend on that initialization crash.

move the entrypoint to cpp code.
The truth cannot be learned ... it can only be recognized.

GregL


Vortex

Another method is to use Agner Fog's objconv tool to rename the complex function ?sum@@YGHHH@Z to the more simple _sum@8 :

objconv -fcoff -nr:?sum@@YGHHH@Z:_sum@8 Sum.obj Sum2.obj