Convert asm64 .c program to .cpp equivalent

Started by Terry Holmes, September 17, 2011, 08:34:56 PM

Previous topic - Next topic

Terry Holmes

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++?

drizz

just tell it to use c name mangling

extern "C" void __cdecl testasm(void);


The truth cannot be learned ... it can only be recognized.

Terry Holmes

Thanks that worked.
But the data sharing--variable p-- still generates unresolved external message.


Terry Holmes

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. 


drizz

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.


The truth cannot be learned ... it can only be recognized.

Terry Holmes

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...

drizz

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

The truth cannot be learned ... it can only be recognized.

Terry Holmes

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.

drizz

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;

The truth cannot be learned ... it can only be recognized.