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
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?
Not random, undname.exe can decode it.
Decorated names (https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170)
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
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:
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
What does the /ALTERNATENAME linker switch do? (https://devblogs.microsoft.com/oldnewthing/20200731-00/?p=104024)
Quote from: TimoVJL on January 28, 2024, 02:51:27 AMWhat does the /ALTERNATENAME linker switch do? (https://devblogs.microsoft.com/oldnewthing/20200731-00/?p=104024)
Hooray, Micros*t reinvented dll hell :biggrin:
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
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.