Solved

Linking Assembler code to a __fastcall C function

Posted on 2000-03-03
17
931 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
Comment Utility
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
Comment Utility
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
Comment Utility
Hmm, what performance gain are you supposed to get using __fastcall?
0
 
LVL 3

Expert Comment

by:sumant032199
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
[ 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
Comment Utility
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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 4

Expert Comment

by:nils pipenbrinck
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

744 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now