【问题标题】:Object specified more than once - unresolved external symbol when calling asm code from C++多次指定对象 - 从 C++ 调用 asm 代码时未解析的外部符号
【发布时间】:2020-07-27 08:42:41
【问题描述】:

我在 .asm 文件中有一些 x86 代码,我正在尝试从 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;
}

组合

.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  

尝试运行此结果:

LNK4042(警告)多次指定对象,忽略额外内容(asm 对象文件)

LNK2019(错误)无法解析的外部符号 _addInts 在函数 _main(asm 目标文件)中引用

由于未解决的外部(解决方案可执行文件),最后的反抗行为采取致命错误 LNK1120 的形式

我正在使用带有 MSVC v142 和 MASM 的 Visual Studio 2019。我的其他自包含汇编代码没有问题,我编写的另一个函数涉及从 C++ 读取 x86 中的 int 数组工作正常。我真的看不出这里出了什么问题,如果是我的代码有问题,一些深奥的设置,或者完全是其他什么。

如果我将 Asm 代码的最后一行更改为 END addInts,那么程序将运行并立即退出,std::cout 中没有任何内容。

解决方案文件没有在链接器设置中定义入口点,这是我为最后一段从 C++ 调用 asm 的代码所做的。

asm 文件包含在构建中,使用 Microsoft Macro Assembler。

cpp 文件设置为编译为 C++,以防万一。

【问题讨论】:

  • 你如何调用你的编译器和链接器(或配置你的IDE来这样做)?这是您的问题中缺少的信息,但对于调查您的问题是必需的。
  • 我正在使用 Visual Studio 调试器 (F5) 运行它。我没想过要包含它,这是我运行所有其他代码的方式,并且没有出现问题。我希望这能回答你的问题,我还没有真正处理过这种事情,可能还不够准确。至于构建设置等,它都是为 x86 设置的,带有 /MACHINE:X86 标志
  • 附加:如果我尝试在没有调试器 (Ctrl-F5) 的情况下运行它,我会得到相同的错误
  • 显示 ML.EXE 的命令行(可以在 .asm 文件属性中看到)。你是按照this guide添加的文件吗?
  • ml.exe /c /nologo /Zi /Fo"Debug\IntegerAddition.obj" /Fl"" /W3 /errorReport:prompt /Ta,它是默认的,与以前工作的其他 asm 文件相同。我将它添加到项目中的方式与链接中描述的几乎相同,除了使用 Win32 而不是 x64

标签: c++ x86


【解决方案1】:

注意到.cpp 文件和.asm 文件具有相同的名称(IntegerAddition.cppIntegerAddition.asm)后,此问题已消除。

将程序集文件重命名为其他内容可解决此问题。

【讨论】:

  • 是的,因为两者都会被编译成IntegerAddition.obj
  • 对自己没有早点看到这一点感到有些失望,但这是完全正确的。
  • 有趣的事实:gcc 对于单行构建命令没有这个问题。你可以毫无问题地做gcc foo.c foo.S -o foo;它对.o 文件使用临时文件名。
猜你喜欢
  • 2013-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 1970-01-01
  • 2013-02-28
  • 2012-11-19
相关资源
最近更新 更多