1

I have some x86 code in a .asm file and am trying to use it from C++:

C++

#include <iostream>

extern "C" int addInts(int a, int b);

int main() {
    
    int a = 1;
    int b = 2;

    int result = addInts(a, b);

    std::cout << "Result :\t" << result << std::endl;

    return 0;
}

Asm

.386
.MODEL  FLAT,   C

.CODE

addInts     PROC

    PUSH    EBP
    MOV     EBP,    ESP

    MOV     EAX,    [EBP+8]
    MOV     ECX,    [EBP+12]

    ADD     EAX,    ECX

    POP     EBP

    RET


addInts     ENDP
END  

Attempting to run this results in:

LNK4042 (warn) object specified more than once, ignoring extras (asm object file)

LNK2019 (error) unresolved external symbol _addInts referenced in function _main (asm object file)

Followed by a final act of defiance taking the form of fatal error LNK1120 due to the unresolved external (solution executable)

I'm using Visual Studio 2019 with MSVC v142 and MASM. My other, self-contained assembly code has had no issues, and another function I've written involving reading int arrays in x86 from C++ worked fine. I really can't see what's going wrong here, if its a problem with my code, some esoteric setting, or something else entirely.

If I change the last line of the Asm code to END addInts then the program just runs and immediately exits with nothing in std::cout.

The solution file has no entry point defined in linker settings, which was what I did for the last piece of code that called asm from C++.

The asm file is included in the build, using Microsoft Macro Assembler.

The cpp file is set to compile as C++, just in case.

vkn
  • 191
  • 12
  • 2
    How do you invoke your compiler and linker (or configured your IDE to do so)? This is an information missing from your question yet mandatory to investigate your issue. – YSC Jul 27 '20 at 08:53
  • I'm running it with Visual Studio debugger (F5). I didn't think to include it, it's how I've run all the other code and there haven't been issues. I hope that answers your question, I haven't really dealt with this kind of thing enough to maybe be exact. As for build settings and such, its all set up for x86, with the /MACHINE:X86 flag – vkn Jul 27 '20 at 08:56
  • Additional: If I try to run it without the debugger (Ctrl-F5) I get the same errors – vkn Jul 27 '20 at 09:07
  • Show the command line of ML.EXE (can be seen in .asm file properties). Did you add the file according to [this guide](https://stackoverflow.com/questions/33751509/external-assembly-file-in-visual-studio)? – rustyx Jul 27 '20 at 09:28
  • `ml.exe /c /nologo /Zi /Fo"Debug\IntegerAddition.obj" /Fl"" /W3 /errorReport:prompt /Ta`, it's default and same as other asm files which have previously worked. I added it to the project in pretty much an identical way to what's described in your link, except using Win32 rather than x64 – vkn Jul 27 '20 at 09:35
  • I fixed it. The problem was caused by the .cpp file and .asm files having the same name... rename and rebuild, everything works now. Thank you to everyone for taking the time to look into this. – vkn Jul 27 '20 at 09:37

1 Answers1

2

This problem was dispelled after noticing that the .cpp file and .asm files had the same names (IntegerAddition.cpp and IntegerAddition.asm).

Renaming the assembly file to something else fixed the issue.

vkn
  • 191
  • 12
  • 1
    Yes, because both would be compiled into `IntegerAddition.obj`. – rustyx Jul 27 '20 at 09:39
  • Somewhat disappointed in myself for not seeing that sooner, but that is exactly correct. – vkn Jul 27 '20 at 09:41
  • Fun fact: `gcc` doesn't have this problem for one-liners build commands. You can do `gcc foo.c foo.S -o foo` with no problem; it uses temporary filenames for the `.o` files. – Peter Cordes Jul 27 '20 at 13:20