尝试将C ++与Assembly链接时,如何解决此链接器错误? [英] How to solve this linker error I get when trying to link C++ with Assembly?

查看:109
本文介绍了尝试将C ++与Assembly链接时,如何解决此链接器错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试链接C ++文件和Assembly文件.程序集文件定义了一个名为add的C ++函数.我正在使用64位Mac OS.尝试编译程序时出现以下错误:

I'm trying to link a C++ file and an Assembly file. The Assembly file defines a C++ function called add. I'm using a 64 bit Mac OS. I get the following error when I try to compile the program:

Undefined symbols for architecture x86_64:
  "_add", referenced from:
      _main in main-d71cab.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main.o] Error 1

Makefile

hello: main.o hello.o
  g++ main.o hello.o -o hello

hello.o: hello.asm
  nasm -f macho64 hello.asm -o hello.o

main.o: main.cpp
  g++ main.cpp -o main.o   

hello.asm

global add

segment .text
add:
  mov           rax, rdi
  add           rax, rsi
  ret

main.cpp

#include <iostream>

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

int main(int argc, char* argv[]) {

  int a, b;

  std::cout << "Enter two numbers\n";
  std::cin >> a;
  std::cin >> b;
  std::cout << "Sum of a and b is " << add(a, b) << std::endl;

  return 0;
}

非常感谢您的帮助.谢谢!

I'd really appreciate any help. Thanks!

推荐答案

在OS/X上, C 的调用约定是:导出时,函数必须在其下划线(除非被覆盖).以便从 C 可见.您说的是 add 在将extern "C"放在此原型上时正在使用 C 调用约定:

On OS/X, the C calling convention is that functions must have an underscore on them (unless it is overridden) when exported from an object in order to be visible to C. You are saying that add is using C calling convention when you put extern "C" on this prototype:

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

这实际上是正确的,但是为了使汇编代码符合要求,您还需要确保对 C/C ++ 代码而言是全局且可见的汇编函数具有前导强调他们.您的汇编代码将像这样开始:

This is in fact correct, but in order for your assembler code to conform you also need to make sure your assembler functions that are going to be global and visible to C/C++ code have a leading underscore on them. Your assembler code would start like this:

global _add

segment .text
_add:


您遇到的另一个问题是您的Makefile和从main.cpp生成main.o的方式.


The other problem you have is in your Makefile and the way you generate main.o from main.cpp.

main.o: main.cpp
  g++ main.cpp -o main.o 

这告诉g++main.cpp编译为名为main.o可执行文件.您真正想做的是告诉g++跳过到可执行部分的链接,并且输出文件main.o实际上将是一个对象.为此,将行更改为:

This tells g++ to compile main.cpp to an executable called main.o . What you really want to do is tell g++ to skip the linking to an executable part, and that the output file main.o will actually be an object. To do that change the line to be:

main.o: main.cpp
   g++ -c main.cpp -o main.o

-c选项表示跳过链接阶段(生成可执行文件并仅输出稍后将链接的对象).

The -c option says to skip the linking stage (that generates an executable and simply output an object that will be linked later).

在尝试制作main.o时没有进行此更改,它认为您需要可执行文件,并且找不到函数_add,因为它不在它所知道的文件中.它在hello.o中,但是命令g++ main.cpp -o main.o不知道.

Without this change when it tries to make main.o, it thinks you want an executable, and can't find the function _add because it is isn't in a file it knows about. It is in hello.o but the command g++ main.cpp -o main.o doesn't know that.

这篇关于尝试将C ++与Assembly链接时,如何解决此链接器错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆