I have a program proto.c which calls asm program test64.asm as follows
#include <windows.h> //etc...
void test64();
__int64 *p;
int main(int argc, char* argv[] ) {
...
test64();
...
}
And the asm program starts as follows:
.code
EXTERN p:PTR SBYTE
test64 PROC
mov r9,p
.... ;etc....
When I rename the proto.c to proto.cpp I get the following compile errors--
error LNK2019: unresolved external symbol "void __cdecl testasm(void)"
error LNK2019: unresolved external symbol p
What needs to change to get this (working) program to work in c++?
just tell it to use c name mangling
extern "C" void __cdecl testasm(void);
Thanks that worked.
But the data sharing--variable p-- still generates unresolved external message.
A less-than-perfect solution that seems to work is to pass the address of the array "p" into the routine as an argument:
extern "C" void __cdecl testasm(__int64 x);
__int64 p;
.
.
.
.
testasm( (int)p );
The argument arrives in the RCX register. The asm code declarations don't seem to care what arguments are declared in the .cpp file. MSDN confirms that RCX is reliable.
oops meant
__int64 *p;
Again, use extern "c" for any shared label.
extern "C" __int64 *p;
extern p:ptr sqword
testasm( (int)p );
- chopping off pointers is not a good idea..., remember int is 32bit
- global variables are not necessary to share data, just read about win64 calling convention (arg1=rcx, arg2=rdx, etc. etc.)
/////////////////////////////////////////////
extern "C" bool test64(__int64 *data);
int main(int argc, char* argv[] ) {
__int64 *data;
if (test64(data)) {
}
}
/////////////////////////////////////////////
test64 proc p:ptr sqword
; p == rcx
mov eax,1
ret
test64 endp
QuoteThe asm code declarations don't seem to care what arguments are declared in the .cpp file.
It's only logical that they don't. In 32bit world you have stdcall calling convention that mangles the function name with number of params at the end, for example: _test32@8 would be 2 param function.
Now further discussion depends on what assembler you are using as
jwasm is a much better assembler than ml64.
1. Am using ml64
2. Fixed testasm( (int)p ); --to-- testasm ( (__int64)p );
3. No combination of
extern "C" __int64 *p;
-or-
__int64 *p;
with or without
extern p:ptr:sqword
in the .asm file would compile without "unresolved symbol "p" " resulting...
Initialize the pointer.
extern "C" __int64 *p = 0;
Or you can declare p in the asm file
.data?
public p
PSQWORD typedef ptr SQWORD
p PSQWORD ? ;; extern "C" __int64 *p;
.code
OR you can dump c++ mangled name for "__int64 *p" which is "?p@@3PEA_JEA" and use
__int64 *p; // C++
extern ?p@@3PEA_JEA:qword;; ASM
mov rax,?p@@3PEA_JEA
Yes, the initialization worked.
extern "C" __int64 *p = 0;
Thanks drizz. I wonder if this is documented somewhere by MS. I would not have found it with Google.
Ok, the right way is to have two declarations, this also works for gcc(TDM-GCC-MinGW64) which otherwise gives a warning for initialized extern.
extern "C" __int64 *p;
__int64 *p;