2

I am using Visual Studio 2019 Community edition and I'm trying to run an Assembly function from a C program.

I get the following error:

  Rebuild started...
    1>------ Rebuild All started: Project: ArrayReverser, Configuration: Debug Win32 ------
    1>Assembling GetValueFromASM.asm...
    1>ArrayReverser.cpp
    1>ArrayReverser.obj : error LNK2019: unresolved external symbol __imp__srand referenced in function _main
    1>ArrayReverser.obj : error LNK2019: unresolved external symbol __imp__rand referenced in function _main
    1>ArrayReverser.obj : error LNK2019: unresolved external symbol __imp____acrt_iob_func referenced in function _printf
    1>ArrayReverser.obj : error LNK2019: unresolved external symbol __imp____stdio_common_vfprintf referenced in function __vfprintf_l
    1>C:\Users\firas\source\repos\ArrayReverser\Debug\ArrayReverser.exe : fatal error LNK1120: 4 unresolved externals
    1>Done building project "ArrayReverser.vcxproj" -- FAILED.
    ========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

I have tried almost every solution I could find on the internet, but nothing worked, I hope someone could give an insight on what is happening.

here is the C Code:

#include <iostream>
#include <stdlib.h>



extern "C" void GetValueFromASM(int* y, const int *x, int n);


int main(int argc, char* argv[])
{
    const int n = 10;
    int x[n], y[n];
    srand(41);
        for (int i = 0; i < n; i++)
            x[i] = rand() % 1000;
        GetValueFromASM(y, x, n);


printf("\n---------------Array Reverser-------------\n");
        for (int i = 0; i < n; i++)
        {
            printf("i:     %5d       y: %5d         x: %5d\n", i, y[i], x[i]);
        }

        return 0;
}  
    

and here is the Assembly Code:

.386 
.model flat,c
.code 
 GetValueFromASM  PROC
               push ebp  ;we pushed the register ebp onto the stack
               mov  ebp,esp  
               push esi
               push edi
               
               xor  eax,eax
               ;now we load the parameters (int* y, const int* x, int n) onto edi,esi,ecx
               mov  edi,[ebp+8]  ;bp - stack base Pointer Register 
               mov  esi,[ebp+12]
               mov  ecx,[ebp+16] 
               
               
               ; in order to reverse the array elemtns we use the following command
               lea esi,[esi+ecx*4-4] 
               pushfd
               std
               
    @@:        lodsd 
               mov [edi], eax
               add  edi, 4
               dec  ecx
               jnz @B
               
               popfd
               mov eax,1
               
               
               ;Epilouge
               pop edi
               pop esi
               pop ebp
     
    GetValueFromASM endp
end     

link to my project files: https://drive.google.com/file/d/1entjG8nHarDTW0AEmvKhv0Cvrw9v0BF2/view?usp=sharing

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 1
    Make sure you have `#include ` as well. Are you linking with `legacy_stdio_definitions.lib`? Does your project compile if you remove the assembly? It looks like the stdio stuff is only used from C, so the assembly is just noise, not part of the problem. – Jester Nov 14 '20 at 00:01
  • 2
    Trying every solution is generally a bad idea when it comes to MSVC config. In fact, great care should be taken to not change anything you don't know the effect of. It might be worthwhile now to create a fresh new project. – rustyx Nov 14 '20 at 00:19
  • 1
    Does this answer your question? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Ken White Nov 14 '20 at 00:30
  • @Jester I included that library, nothing changed. – Firas Abd El Gani Nov 14 '20 at 13:17
  • @MichaelPetch I did that. unfortunately, it's still not working. – Firas Abd El Gani Nov 14 '20 at 13:46
  • @rustyx, I opened a new project, and tried to apply what people said here, it's still not working. – Firas Abd El Gani Nov 14 '20 at 13:47
  • Upload your entire project zip somewhere so we can see. – rustyx Nov 14 '20 at 13:57
  • @rustyx, here is a link to the project files: https://drive.google.com/file/d/1entjG8nHarDTW0AEmvKhv0Cvrw9v0BF2/view?usp=sharing – Firas Abd El Gani Nov 14 '20 at 15:12

1 Answers1

5

I downloaded your project and observed similar linker errors (I had more of them actually). I reviewed all the linker options for the project paying attention to the entries that were bold. The options in bold have not been inherited. One that stood out was Entrypoint:

enter image description here

You overrode the default C startup entrypoint with your MASM function Reverser. I modified the EntryPoint so that it was blank (removed it). When I rebuilt the project there were no longer linker errors.

Your Reverser function has no ret at the end so it will throw an exception when run. I added a ret to the bottom of the Reverser function and ran the code and got this output:

enter image description here


Note: @rustyx had very good advice "Trying every solution is generally a bad idea when it comes to MSVC config. In fact, great care should be taken to not change anything you don't know the effect of. It might be worthwhile now to create a fresh new project." . If you create a fresh new CONSOLE project and don't modify the entry point there should be no problems.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 1
    Any guesses why something that sounds like a run-time issue results in linker errors? – Jester Nov 14 '20 at 20:27
  • 1
    @Jester : I did a cursory look. It is almost like the assumption is that if you alter the Entrypoint you are no longer interested in the C runtime. Removing the Entry point only adds the extra option for the entry point and neither adds to the linker options (I compared the entire command line between them) nor adds to the C/C++ compiler options. This seems to be some behaviour with the linker. – Michael Petch Nov 14 '20 at 22:30