News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Calling a C++ function

Started by Vortex, January 19, 2024, 06:14:32 AM

Previous topic - Next topic

Vortex

Poasm sample calling a MS VC module :

#define _NO_CRT_STDIO_INLINE

#include <stdio.h>

class formula {

    public:
       
        int calc(int, int, int, int, int);
        void GetResult(int);
};

int formula::calc(int a, int b, int c, int d, int e)
{
    return a * b * c * d * e;
}

void formula::GetResult(int t)
{
    printf("The result is %u\n",t);
}

?calc@formula@@QEAAHHHHHH@Z PROTO :QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD
calc TEXTEQU <?calc@formula@@QEAAHHHHHH@Z>

?GetResult@formula@@QEAAXH@Z PROTO :QWORD,:QWORD
GetResult TEXTEQU <?GetResult@formula@@QEAAXH@Z>

ExitProcess PROTO :QWORD

.code

start PROC PARMAREA=6*QWORD

;   rcx ->  this pointer

    invoke  calc,rcx,2,4,6,8,10

;   rcx ->  this pointer

    invoke  GetResult,rcx,rax

    invoke  ExitProcess,0

start ENDP

END start

jj2007

So it's more or less like normal C invokes, but with C++ syntax. I've always wondered what these QEAAHHHHHH etc sequences mean. Randomly generated, or for runtime parameter checks?

TimoVJL

May the source be with you

Vortex

Hi Jochen,

Agner Fog's document :

Quote5. Calling conventions for different C++ compilers and operating systems
This document contains details about data representation, function calling conventions, register usage conventions, name mangling schemes, etc. for many different C++ compilers and operating systems. Discusses compatibilities and incompatibilities between different C++ compilers. Includes information that is not covered by the official Application Binary Interface standards (ABI's). The information provided here is based on my own research and therefore descriptive rather than normative. Intended as a source of reference for programmers who want to make function libraries compatible with multiple compilers or operating systems and for makers of compilers and other development tools who want their tools to be compatible with existing tools.

https://www.agner.org/optimize/calling_conventions.pdf

jj2007

Quote from: Vortex on January 20, 2024, 05:23:42 AMmake function libraries compatible with multiple compilers

Thanks, Erol. I am always impressed by the claim of C/C++ compilers to be "standardised" and "compatible" :bgrin:

Vortex

Code updated to remove the name mangling :

calc PROTO :QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD

GetResult PROTO :QWORD,:QWORD

ExitProcess PROTO :QWORD

.code

start PROC PARMAREA=6*QWORD

;   rcx ->  this pointer

    invoke  calc,rcx,2,4,6,8,10

;   rcx ->  this pointer

    invoke  GetResult,rcx,rax

    invoke  ExitProcess,0

start ENDP

END start

\PellesC\bin\polink /SUBSYSTEM:CONSOLE /LARGEADDRESSAWARE /LIBPATH:\PellesC\lib\Win64 /ALTERNATENAME:GetResult=?GetResult@formula@@QEAAXH@Z /ALTERNATENAME:calc=?calc@formula@@QEAAHHHHHH@Z CallCppFunc.obj Class.obj kernel32.lib msvcrt.lib



Vortex

Hi Timo,

Thanks for explaining the linker option ALTERNATENAME.

Hi Jochen,

This option of Polink\MS Link is useful. You can modify the function names ( even API functions ) to redirect them to other symbols.

.386
.model flat,stdcall
option casemap:none

msvc_printf PROTO C :DWORD,:VARARG
msvc_scanf  PROTO C :DWORD,:DWORD
msvc_strupr PROTO C :DWORD

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

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\msvcrt.lib

.data

string1     db 'What is your name?',13,10,13,10,0
string2     db 'Nice to meet you %s',13,10,0
f1          db '%s',0

.data?

szName      db 32 dup(?)

.code

start:

    invoke  msvc_printf,ADDR string1
    invoke  msvc_scanf,ADDR f1,ADDR szName

    invoke  msvc_strupr,ADDR szName
    invoke  msvc_printf,ADDR string2,eax

    invoke  ExitProcess,0

END start

Build.bat :

\masm32\bin\ml /c /coff scanf.asm
\masm32\bin\polink /SUBSYSTEM:CONSOLE /ALTERNATENAME:_msvc_scanf=_scanf /ALTERNATENAME:_msvc_printf=_printf /ALTERNATENAME:_msvc_strupr=__strupr scanf.obj

jj2007

Quote from: Vortex on January 28, 2024, 06:47:47 AMThis option of Polink\MS Link is useful.

Hi Erol,

It can be useful sometimes, no doubt. However, when you read the linked page, it becomes clear that Microsoft creates the absolute chaos again.

BOOL (WINAPI * const _pDefaultRawDllMain)(HANDLE, DWORD, LPVOID) = NULL;
#if defined (_M_IX86)   
#pragma comment(linker, "/alternatename:__pRawDllMain=__pDefaultRawDllMain")   
#elif defined (_M_IA64) || defined (_M_AMD64)   
#pragma comment(linker, "/alternatename:_pRawDllMain=_pDefaultRawDllMain")   
#else  /* defined (_M_IA64) || defined (_M_AMD64) */   
#error Unsupported platform   
#endif  /* defined (_M_IA64) || defined (_M_AMD64) */ 
QuoteThe C++/WinRT library uses /ALTERNATENAME for a different purpose. The C++/WinRT library wants to support being used both with and without windows.h, so it contains its own declarations for the Windows functions and structures that it needs.

But now there's a problem: If it is used with windows.h, then there are structure definition errors. Therefore, C++/WinRT needs to give its equivalent declarations of Windows structures some other name, to avoid redefinition errors.

But this in turn means that the function prototypes in the C++/WinRT library need to use the renamed structures, rather than the original Windows structures, in case the C++/WinRT library is used without windows.h. This declaration will in turn create a conflict if the C++/WinRT library is used with windows.h when the real declarations are encountered in windows.h.

The solution is to rename the C++/WinRT version of Windows functions, too. C++/WinRT gives them a WINRT_IMPL_ prefix, so that there is no function declaration collision.

We now have two parallel universes. There's the windows.h universe, and the C++/WinRT universe, each with their own structures and functions. The two parallel universes are unified by the /ALTERNATENAME directive

This is madness.