Solved

Linking Assembler code to a __fastcall C function

Posted on 2000-03-03
17
947 Views
Last Modified: 2008-02-01
How do I call the C function
int __fastcall QuickAllocate (int size);
from my assembly code? This is not inline assembler, but a real assembly code file, I use ml.exe to assemble it. If I use the code
...
extern @QuickAllocate@4:near
...
call @QuickAllocate@4
...
I get the linker error
"error LNK2001: unresolved external symbol _@QuickAllocate@4"

The assembler seems desperate to add the _ name decoration to the C function name, but that is not correct in the case of __fastcall, so even though I specify the correct name decoration it won't leave it alone.

Using VC++ 6.0 and ml version 6.11

0
Comment
Question by:mgrinnell
  • 7
  • 2
  • 2
  • +4
17 Comments
 
LVL 2

Expert Comment

by:tdubroff
ID: 2581991
Intead of using _fastcall, try extern "C".  This should prevent name-mangling from occuring at all.  Then in your assembly just use extern QuickAllocate : near.
0
 

Author Comment

by:mgrinnell
ID: 2582082
Yes, that would definitely work, that's what it was before!  What I'm trying to do here is change the calling convention for performance, though. __fastcall is what I want, so I need to find out how to make the assembler let me do it.
0
 
LVL 2

Expert Comment

by:tdubroff
ID: 2582128
Hmm, what performance gain are you supposed to get using __fastcall?
0
NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

 
LVL 3

Expert Comment

by:sumant032199
ID: 2582544
I am not good in Assembly but what I think is you can get address of your C function very easily and using pointer to the function and then instructing assembler to start execution from that vector.
0
 

Author Comment

by:mgrinnell
ID: 2583320
I tried that too -- treating the function pointer as just an address and jumping to it. I had the same name decoration problem with that, i.e. even pretending QuickAllocate was just a data pointer it wouldn't let me use it without predefining it, and if I predefine it, the assembler insists on prepending an _ character when it tells the linker what to look for.
0
 

Author Comment

by:mgrinnell
ID: 2583322
tdubroff, when you use __fastcall, you can pass arguments in registers instead of pushing them on the stack and then popping them off.
0
 
LVL 11

Expert Comment

by:alexo
ID: 2583816
[ VC++ 4.2 ]

The __fastcall calling convention passes the first two arguments of size doubleword (DWORD) or smaller in the ECX and EDX registers; the remaining arguments are pushed on the stack right to left.  The called function adjusts the stack, and no case translation takes place.

Name-decoration convention - At sign (@) is prefixed to names; an at sign @ followed by the number of bytes (in decimal) in the parameter list is suffixed to names.

----------

You can use a .DEF file to set an alias to the mangled ("decorated") name.
0
 
LVL 11

Expert Comment

by:alexo
ID: 2583825
Some more:

The current 32-bit module-definition (.DEF) file syntax requires that __cdecl, __stdcall, and __fastcall functions be listed in the EXPORTS section without underscores (undecorated).
0
 
LVL 4

Expert Comment

by:nils pipenbrinck
ID: 2584556
Hm...

I've done a lot asm programming under win32.. but I always used nasm or tasm... never masm.

Maybe I don't understood your problem: it's just, that your assembler puts a underscore before your symbol, right?

0
 

Author Comment

by:mgrinnell
ID: 2586365
That's right, the problem is just that I need to name the C function I want to call to masm. The plain name of the function is QuickAllocate; the decorated name is @QuickAllocate@4. No matter what I do, the assembler puts an underscore in front of any symbol I name.
0
 
LVL 4

Expert Comment

by:nils pipenbrinck
ID: 2586899
Hm.. I have no idea execept switching to tasm or nasm.


nasm does no name decoration at all..

with tasm you can control the name decoration.. (using a .model switch)

Nils
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 2593913
The easiest way to get this to work is to use the compiler to help.

First create your calling program (which I call test.cpp)

#include <stdio.h>

extern "C"
{
      int __fastcall Foo();
}

int main(int argc, char* argv[])
{
      int a = Foo();
      printf("a = %d\n", a);
      return 0;
}

Note the declaration for Foo (which has __fastcall).

Next, create a dummy C++ file. We will use this dummy C++ to create the dummy stub for the assembly file. I call this file Foo.cpp

extern "C"
{
int __fastcall Foo()
{
      return 0;
}
}

Next on the command line, use

  cl /c /FA foo.cpp

to generate the foo.asm file:

      TITLE      foo.cpp
      .386P
include listing.inc
if @Version gt 510
..model FLAT
else
_TEXT      SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT      ENDS
_DATA      SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA      ENDS
CONST      SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST      ENDS
_BSS      SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS      ENDS
_TLS      SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS      ENDS
FLAT      GROUP _DATA, CONST, _BSS
      ASSUME      CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC      @Foo@0
_TEXT      SEGMENT
@Foo@0      PROC NEAR
      push      ebp
      mov      ebp, esp
      xor      eax, eax
      pop      ebp
      ret      0
@Foo@0      ENDP
_TEXT      ENDS
END


You can then compare your assembly file to this one to find out what is different. Another possible method is to put your code in here. Either way, you should have no problems continuing.


0
 

Author Comment

by:mgrinnell
ID: 2594371
Thanks thui, but this is not exactly the problem I'm trying to solve. I have an existing fastcall function written in C, whose prototype looks like
  int __fastcall QuickAllocate (int size);
I want to call that function from an assembler module.  

What's interesting in your example, though, is the beginning of the assembler file. If version is > 510 (which I presume it is) the file starts with a .model statement instead of the old _TEXT SEGMENT DWORD USE32 etc.., which is what my assembler file starts with. Maybe there's a clue here, I don't know yet...
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 2597119
You would use the same technique, create a dummy .cpp file

extern "C"
{
extern int __fastcall QuickAllocate(int size);
}

void DummyCaller()
{
  QuickAllocate(3);
}

And generate the assembly file for it and compare with your program.
0
 

Author Comment

by:mgrinnell
ID: 2774443
This generated the same code that I already tried, e.g.

EXTRN      @QuickAllocate@4:NEAR

When I try to use this from my assembly code, the assembler generates instructions to the linker to try to link to _@QuickAllocate@4 instead of @QuickAllocate@4.
0
 

Accepted Solution

by:
mgrinnell earned 100 total points
ID: 2774471
A friend discovered the answer. fastcall is the Microsoft C compiler's replacement for syscall, but you actually have to still use syscall with masm. If I declare QuickAllocate as

extrn syscall @QuickAllocate@4:near

then the linker knows not to modify the function name by prepending an _ character.

I'm going to try to figure out how to post this solution to the Community Support topic area, too. Thanks to all for your help.

0
 
LVL 3

Expert Comment

by:darinw
ID: 2775566
Hello everyone,

I am moving this question to the PAQ.

-- I am accepting one of mgrinnell's comments as an answer --

darinw
Customer Service
0

Featured Post

Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question