News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

EXTERN "C" Calling conventions in GoASM

Started by FlySky, August 27, 2011, 09:45:57 AM

Previous topic - Next topic

FlySky

Is there any documentation about External "C" calling conventions in GoASM.

I am playing with the following C code which I am trying to translate to use with GoASM:

// #1: XWSAStartup
extern "C"  int __stdcall XWSAStartup (WORD wVersionRequested, LPWSADATA lpWsaData) {
   lpWsaData->wVersion = 2;
   return 0;
}

I've tried using:

_XWSAStartup@8 frame wVersionRequested, lpWsaData
mov eax, [lpWsaData]
mov w[eax+WSADATA.wVersion]
xor eax, eax
ret
endf

But somehow this is not working at all. I found out about using the _xxxx@8 from a post made by Jeremy. But comparing the compiled c file with the goasm compiled in IDA they are not looking the same in anyway.

.text:10001070 ; __stdcall XWSAStartup(x, x)
.text:10001070                 public _XWSAStartup@8
.text:10001070 _XWSAStartup@8  proc near 

From the compiled C file it perfectly created the external C label. But in Goasm it simply doesn't look like that in anyway.



Vortex

Hi FlySky,

Could you try this GoAsm switch?

/ms=decorate for ms linker

Also, modify _XWSAStartup@8 to XWSAStartup

Vortex

Here is an example for you :

MsgBox.asm :

.data

title   db 'Demo',0

.code

MsgBox FRAME message

    invoke  MessageBoxA,0,[message],ADDR title,0
    ret

MsgBox ENDF


Demo.cpp :



extern "C" int __stdcall MsgBox(char *message);
extern "C" int __stdcall ExitProcess(unsigned int uExitCode);


void WinMain()
{
   char *msg="GoAsm demo";
   MsgBox(msg);
   ExitProcess(0);
}


Building the project wit VC++ :

\goasm\goasm /ms MsgBox.asm
cl /Zl /c /Ogtyb2 /Gs /G6 /Gz /FoDemo.OBJ Demo.cpp
\masm32\bin\polink /SUBSYSTEM:WINDOWS /LIBPATH:\masm32\lib /entry:WinMain@0 Demo.obj MsgBox.obj kernel32.lib user32.lib


FlySky

Vortex thanks for your posts and information.

Maybe I am misunderstanding the concept of External functions.

I am playing with windows network API's atm on a small tool I made.
Basicly what I am working on is creating a wrapper dll.
The dll is created and placed in the same dir as the tool is executing from. Now it does not load the system Winsock.dll
but my wrapper dll, and that's where I am trying to use the XWSAStartup function from.
Using the C created file calling the function goes fine.
Doing it with an GoASM dll it's not working. So I assumed it had to do with the external calling.

Comparing both compiled functions:

From C

.text:10001070 ; __stdcall XWSAStartup(x, x)
.text:10001070                 public _XWSAStartup@8
.text:10001070 _XWSAStartup@8  proc near               ; DATA XREF: .rdata:off_1000C858o
.text:10001070
.text:10001070 arg_4           = dword ptr  0Ch
.text:10001070
.text:10001070                 push    ebp
.text:10001071                 mov     ebp, esp
.text:10001073                 mov     eax, 2
.text:10001078                 mov     ecx, [ebp+arg_4]
.text:1000107B                 mov     [ecx], ax
.text:1000107E                 push    offset aXwsastartup ; "XWSAStartup \n"
.text:10001083                 call    trace
.text:10001088                 add     esp, 4
.text:1000108B                 xor     eax, eax
.text:1000108D                 pop     ebp
.text:1000108E                 retn    8
.text:1000108E _XWSAStartup@8  endp

GoASM:
code:10001013
code:10001016 ; ---------------------------------------------------------------------------
code:10001016                 push    ebp
code:10001017                 mov     ebp, esp
code:10001019                 mov     eax, [ebp+0Ch]
code:1000101C                 mov     word ptr [eax], 2
code:10001021                 xor     eax, eax
code:10001023                 pop     ebp
code:10001024                 retn    8

Maybe it's the calling convention that I need to change


Yuri

From what I see, extern "C" simply undecorates the exported names.
For example, without extern "C" the exported name is "int __cdecl TestFunc(int,int)".
With extern "C" it's just "TestFunc".

Vortex

Quote from: Yuri on August 29, 2011, 03:56:38 AM
From what I see, extern "C" simply undecorates the exported names.
For example, without extern "C" the exported name is "int __cdecl TestFunc(int,int)".
With extern "C" it's just "TestFunc".

Hi Yuri,

I am afraid that is not true. Disassembling Demo.obj :


.386
option dotname
.model flat

public _WinMain@0

extern _MsgBox@4: near
extern _ExitProcess@4: near

@comp.id equ 000B224FH


_data   SEGMENT DWORD PUBLIC 'DATA'

$SG272  label byte
        db 47H, 6FH, 41H, 73H, 6DH, 20H, 64H, 65H       ; 0000 _ GoAsm de
        db 6DH, 6FH, 00H                                ; 0008 _ mo.

_data   ENDS

_text   SEGMENT PARA PUBLIC 'CODE'

_WinMain@0 PROC NEAR
        push    offset $SG272
        call    _MsgBox@4
        push    0
        call    _ExitProcess@4
        ret
_WinMain@0 ENDP


As you can see, all the functions are decorated.

If you remove the "C" statements, the result will be like the following :

extern int __stdcall MsgBox(char *message);
extern int __stdcall ExitProcess(unsigned int uExitCode);


.386
option dotname
.model flat

public _WinMain@0

extern ?MsgBox@@YGHPAD@Z: near
extern ?ExitProcess@@YGHI@Z: near


This decoration type is specific to MS VC++  Other C++ compiler can have different decoration conventions.

Yuri

Hmm... Actually I was talking about DLLs. When I build one (in VS2008 Express) with the exported function marked as extern "C" and then look into the DLL via Dll Export Viewer, I see that the exported name is exactly the name of my function in the source code, e.g. TestFunc. If I don't use extern "C", the exported name looks like "int __cdecl TestFunc(int,int)".

Maybe I used the term "decorated" wrongly. Sorry if so.

Honestly I am not quite sure what problem FlySky is struggling with. But he said he was trying to build a wrapper DLL. So I assumed it was some issue with the names of the functions exported by that DLL.

FlySky

Yuri and Vortex thanks for the replies so far.
I've included the GoASM source and the C-compiled DLL.

The thing is the following, using the C-compiled DLL the program is able to communicate properly with it.
Using the GoASM project it can't communicate properly with it.
Since the C-compiled dll (test1 function) is using the EXTERN "C" decoration I was assuming that was the problem.
As when comparing both DLL's in IDA, the C-compiled DLL is nicely generating an export while GoASM doesn't.
So the question was how would I be able to do the same in GoAsm what the C-compiled version looks like.

donkey

Hi Flysky,

I haven't had much time to look at your problem but I have also had fits when using C libraries. I've had some success with the /mix switch for GoLink.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Vortex

Quote from: FlySky on August 29, 2011, 05:52:14 PM
Since the C-compiled dll (test1 function) is using the EXTERN "C" decoration I was assuming that was the problem.

Hi FlySky,

EXTERN "C" is a bit confusing here as your source code is C and not C++   The EXTERN "C" statement is specific to C++ if I am not wrong.

wjr

Remove the space and use "EXPORT:5332" as well as omitting the ":NONAME" part, since that will not include the function for export by name in the DLL (only by ordinal). How about this...


EXPORT:5332
XWSAStartup FRAME wVersionRequested, lpWsaData
;
;
ENDF

Yuri

You can decorate the name manually in GoAsm source:

export _test_1@8 FRAME param1, param2
    mov eax,1
    ret
ENDF


But the problem may be the wrong calling convention, since the FRAME directive is intended for Windows callback functions, which use stdcall, while your C DLL probably uses cdecl. To do this in GoAsm, you have to write your functions without FRAMEs.

GregL

Quote from: VortexThe EXTERN "C" statement is specific to C++ if I am not wrong.

Vortex is correct. You don't need extern "C" with C.  It is used with C++ to undecorate mangled names.

FlySky

Quote from: wjr on August 29, 2011, 07:46:52 PM
Remove the space and use "EXPORT:5332" as well as omitting the ":NONAME" part, since that will not include the function for export by name in the DLL (only by ordinal). How about this...


EXPORT:5332
XWSAStartup FRAME wVersionRequested, lpWsaData
;
;
ENDF


Sorry for the later reply. The issues is perfectly fixed using what WJR suggested. I didn't find this in GoASM documentation though. Exporting by ordinals fixed the problems. Thanks for all suggestion guys.