Unresolved external symbol C++ with Assembler

6.3k views Asked by At

I am trying to make function in assembler to use it in C. My problem is that i can't compile my code. I am using Visual studio 2012. I've add masm in build custiomization so i dont have idea whats wrong. C:

#include <stdio.h> 
int szukaj_max (int a, int b, int c);

int main() 
{ 
int x, y, z, wynik; 
printf("\nProszępodaćtrzy liczby całkowite: "); 
scanf_s("%d %d %d", &x, &y, &z, 32);

wynik = szukaj_max(x, y, z); 
printf("\nSpośród podanych liczb %d, %d, %d, \ liczba %d jest największa\n", x,y,z, wynik);

return 0; 

Assembly:

.686 
.model flat 
public _szukaj_max 
.code 
_szukaj_max  PROC 
    push  ebp   ; zapisanie zawartości EBP na stosie 
    mov   ebp, esp  ; kopiowanie zawartości ESP do EBP 
    mov   eax, [ebp+8]  ; liczba x 
    cmp   eax, [ebp+12]  ; porownanie liczb x i y 
jge   x_wieksza  ; skok, gdy x >= y 
; przypadek x < y 
    mov   eax, [ebp+12]  ; liczba y 
    cmp   eax, [ebp+16]  ; porownanie liczb y i z 
jge   y_wieksza  ; skok, gdy y >= z 
; przypadek y < z 
; zatem z jest liczbąnajwiekszą
wpisz_z:  
    mov  eax, [ebp+16]  ; liczba z 
zakoncz: 
    pop   ebp 
    ret 
x_wieksza: 
    cmp   eax, [ebp+16]  ; porownanie x i z 
    jge   zakoncz   ; skok, gdy x >= z 
    jmp   wpisz_z 
y_wieksza: 
    mov   eax, [ebp+12]  ; liczba y 
    jmp   zakoncz 
_szukaj_max  ENDP

END 

Error:

 Error  2   error LNK2019: unresolved external symbol "int __cdecl szukaj_max(int,int,int)" (?    szukaj_max@@YAHHHH@Z) referenced in function _main    C:\Users\Kaczor\Desktop\Ako\4.1\4.1\Source.obj
 Error  3   error LNK1120: 1 unresolved externals   C:\Users\Kaczor\Desktop\Ako\4.1\4.1\Debug\4.1.exe   1
3

There are 3 answers

0
Peter - Reinstate Monica On BEST ANSWER

The compiler of the main file containing the function call assumes it is a C++ file, for example because the file name ends in ".cpp". Therefore, the compiler interpretes the declaration int szukaj_max (int a, int b, int c); as declaring a C++ function. However, your assembler file defines a C function.

The main difference is in name mangling: The symbol names generated for C++ functions contain information about the parameters, mainly in order to facilitate overload resolution by the linker. Therefore the simple symbol _szukaj_max is not even looked for. (I was initially confused by __cdecl appearing in the error message, but that defines ABI issues like the order of parameter passing, stack cleanup responsibilities etc., not the name mangling.)

For more information about "decorated names", as Microsoft calls it, see here.

Solution:

  • The canonical and portable way is to declare the function "extern C" in your main file:
    extern "C" int szukaj_max(int a, int b, int c);
  • Name the function the way the compiler and linker expect it. You can probably cobble the name together manually, or you just look at the linker error: The name in your case is ?szukaj_max@@YAHHHH@Z (without leading underscore). This is not portable because other compilers have different conventions. (But then the MASM assembler may not be fully portable either.)
  • Or, if you are actually programming in C, change your main file name's extension to ".c" so that the compiler assumes all declared functions are C functions (that's Ange's correct solution). That should again be portable.
0
Ange On

You have to name the file ".c" not ".cpp" i had the same problem and it was solved by doing so.

0
Walid Moustafa On

I believe some of the solutions could be incomplete, so I am just adding my process, hoping it helps anyone.

Setup is Visual Studio 2015 on x64 Windows 10 with .cpp file extension (compiling for x64). I was trying to run this int2d_x64.asm from al-khaser inside my visual studio MFC application.

I found this article by LALLOUS' LAB, and this answer by Mike Danes on msdn to be fundamentally helpful, and in short:

  1. Add the .asm file to your project (right click project name > add item > existing item > int2d_x64.asm)
  2. Add .asm file compilation support for your project (right click project name > Build Dependencies > Build Customizations > check mark masm and press ok)
  3. Define the .asm file item type as Microsoft Macro Assembler for your file (int2d_x64.asm in my case). (right click the .asm file in the solution explorer > properties > General > From the Item Type drop down menu, choose Microsoft Macro Assembler)
  4. Define the function itself as extern "C" void __int2d(); (For the OP's case, that would be as @Peter - Reinstate Monica suggested : extern "C" int szukaj_max(int a, int b, int c);)