Pelles C forum
Assembly language => Assembly discussions => Topic started by: Vortex on January 07, 2024, 07:46:01 PM
-
Here is a Poasm example 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);
}
rcx points the "this" pointer, it must be skipped :
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
-
Same example with function prototypes :
?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
-
Why not with C ;)
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);
}
-
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 :
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
-
Hi Timo,
I updated my code 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
Linking the object modules :
\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
-
Why not with C ;)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.
-
We are here to test Pelle's C tools, so sometimes we offer test with pure C too, when an example is for poasm.
-
Another alternative is Agner Fog's objconv tool :
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