NO

Author Topic: Calling a C++ function from Poasm  (Read 4621 times)

Offline Vortex

  • Member
  • *
  • Posts: 870
    • http://www.vortex.masmcode.com
Calling a C++ function from Poasm
« on: January 07, 2024, 07:46:01 PM »
Here is a Poasm example calling a MS VC module :

Code: [Select]
#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);
}

rcx points the "this" pointer, it must be skipped :

Code: [Select]
EXTERN ?calc@formula@@QEAAHHHHHH@Z:PROC
calc TEXTEQU <?calc@formula@@QEAAHHHHHH@Z>

EXTERN ?GetResult@formula@@QEAAXH@Z:PROC
GetResult TEXTEQU <?GetResult@formula@@QEAAXH@Z>

ExitProcess PROTO :QWORD

.code

start PROC PARMAREA=6*QWORD

;   rcx ->  this pointer

    mov     rdx,2
    mov     r8,4
    mov     r9,6
    mov     QWORD PTR [rsp+32],8
    mov     QWORD PTR [rsp+40],10
    call    calc

;   rcx ->  this pointer

    mov     rdx,rax
    call    GetResult

    invoke  ExitProcess,0

start ENDP

END start
Code it... That's all...

Offline Vortex

  • Member
  • *
  • Posts: 870
    • http://www.vortex.masmcode.com
Re: Calling a C++ function from Poasm
« Reply #1 on: January 17, 2024, 05:31:24 PM »
Same example with function prototypes :

Code: [Select]
?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

Code it... That's all...

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2122
Re: Calling a C++ function from Poasm
« Reply #2 on: January 18, 2024, 09:48:43 AM »
Why not with C  ;)
Code: [Select]
void __stdcall  ExitProcess( unsigned int uExitCode);
int __cdecl printf(const char * format, ...);
#pragma comment(lib, "msvcrt.lib")
// void formula::GetResult(int t)
// void ?GetResult@formula@@QEAAXH@Z(long long, long long)
#pragma comment(linker, "-alternatename:formula_GetResult=?GetResult@formula@@QEAAXH@Z")
void formula_GetResult(void* this, int t);
// int formula::calc(int a, int b, int c, int d, int e)
// int ?calc@formula@@QEAAHHHHHH@Z(int a, int b, int c, int d, int e)
int formula_calc(void* this, int a, int b, int c, int d, int e);
#pragma comment(linker, "-alternatename:formula_calc=?calc@formula@@QEAAHHHHHH@Z")
void __cdecl mainCRTStartup(void)
{
int x = formula_calc(0,2,4,6,8,10);
formula_GetResult(0,x);
ExitProcess(0);
}
May the source be with you

Offline Vortex

  • Member
  • *
  • Posts: 870
    • http://www.vortex.masmcode.com
Re: Calling a C++ function from Poasm
« Reply #3 on: January 18, 2024, 08:31:10 PM »
Hi Timo,

Great sample, many thanks. Something new to learn for me, it's the /ALTERNATENAME:symbol=symbol option of polink.

The linker option ALTERNATENAME does the job, disassembling the object module produced by Pelles C :

Code: [Select]
public mainCRTStartup

extern ExitProcess: near
extern formula_GetResult: near
extern formula_calc: near

_text   SEGMENT PARA 'CODE'

mainCRTStartup PROC
        sub     rsp, 56
        mov     dword ptr [rsp+28H], 10
        mov     dword ptr [rsp+20H], 8                 
        xor     ecx, ecx                               
        mov     edx, 2                                 
        mov     r8d, 4                                 
        mov     r9d, 6                                 
        call    formula_calc                           
        xor     ecx, ecx                               
        mov     edx, eax                               
        call    formula_GetResult                       
        xor     ecx, ecx                               
        call    ExitProcess                             
        add     rsp, 56                                 
        ret                                             
mainCRTStartup ENDP
Code it... That's all...

Offline Vortex

  • Member
  • *
  • Posts: 870
    • http://www.vortex.masmcode.com
Re: Calling a C++ function from Poasm
« Reply #4 on: January 25, 2024, 08:08:13 PM »
Hi Timo,

I updated my code to remove the name mangling :

Code: [Select]
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

Linking the object modules :

Code: [Select]
\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
Code it... That's all...

Offline WiiLF23

  • Member
  • *
  • Posts: 89
Re: Calling a C++ function from Poasm
« Reply #5 on: February 03, 2024, 11:57:39 PM »
Why not with C  ;)
Code: [Select]
void __stdcall  ExitProcess( unsigned int uExitCode);
int __cdecl printf(const char * format, ...);
#pragma comment(lib, "msvcrt.lib")
// void formula::GetResult(int t)
// void ?GetResult@formula@@QEAAXH@Z(long long, long long)
#pragma comment(linker, "-alternatename:formula_GetResult=?GetResult@formula@@QEAAXH@Z")
void formula_GetResult(void* this, int t);
// int formula::calc(int a, int b, int c, int d, int e)
// int ?calc@formula@@QEAAHHHHHH@Z(int a, int b, int c, int d, int e)
int formula_calc(void* this, int a, int b, int c, int d, int e);
#pragma comment(linker, "-alternatename:formula_calc=?calc@formula@@QEAAHHHHHH@Z")
void __cdecl mainCRTStartup(void)
{
int x = formula_calc(0,2,4,6,8,10);
formula_GetResult(0,x);
ExitProcess(0);
}

I convert everything in this topic category to C. Its generally code already available, uses common techniques etc.

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2122
Re: Calling a C++ function from Poasm
« Reply #6 on: February 04, 2024, 11:32:35 AM »
We are here to test Pelle's C tools, so sometimes we offer test with pure C too, when an example is for poasm.

May the source be with you

Offline Vortex

  • Member
  • *
  • Posts: 870
    • http://www.vortex.masmcode.com
Re: Calling a C++ function from Poasm
« Reply #7 on: February 06, 2024, 08:57:55 PM »
Another alternative is Agner Fog's objconv tool :

Code: [Select]
5 Modifying symbols

It is possible to modify the names of public and external symbols in object files and libraries
in order to prevent name clashes, to fix problems with different name mangling systems,
etc.

Note that symbol names must be specified in the way they are represented in object files,
possibly including underscores and name mangling information. All names are treated as
case sensitive. Use the dump or disassembly feature to see the mangled symbol names.
To change the symbol name name1 to name2 in object file file1.obj:

objconv -nr:name1:name2 file1.obj file2.obj

The modified object file will be file2.obj. Objconv will replace name1 with name2
wherever it occurs in public, external and local symbols, as well as section names and
library member names. All names are case sensitive.

https://www.agner.org/optimize/objconv-instructions.pdf
Code it... That's all...