我正在尝试链接C++文件和程序集文件.Assembly文件定义了一个名为的C++函数add
.我正在使用64位Mac OS.我尝试编译程序时收到以下错误:
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中
#includeextern "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; }
我真的很感激任何帮助.谢谢!
在OS/X上,C调用约定是当从对象导出时,函数必须在它们上面有一个下划线(除非它被覆盖),以便对C可见.你说当你放上这个原型时,add正在使用C调用约定extern "C"
:
extern "C" int add(int a, int b);
这实际上是正确的,但是为了使汇编代码符合您的要求,您还需要确保您的汇编程序函数是全局的并且对C/C++代码可见,它们具有前导下划线.您的汇编程序代码将如下所示:
global _add segment .text _add:
你有另一个问题是在你Makefile
和你生成的方式main.o
从main.cpp
.
main.o: main.cpp g++ main.cpp -o main.o
这告诉g++
编译main.cpp
为一个名为的可执行文件main.o
.你真正想做的是告诉g++
跳过链接到可执行部分,并且输出文件main.o
实际上是一个对象.要做到这一点,改变行:
main.o: main.cpp g++ -c main.cpp -o main.o
该-c
选项表示跳过链接阶段(生成可执行文件并只输出稍后将链接的对象).
如果没有这个改变,它会尝试制作main.o
,它认为你想要一个可执行文件,并且找不到该函数,_add
因为它不在它知道的文件中.它在,hello.o
但命令g++ main.cpp -o main.o
不知道.