如何解决我在尝试使用 Assembly link C++ 时遇到的这个 linker 错误?
How to solve this linker error I get when trying to link C++ with Assembly?
我正在尝试 link 一个 C++ 文件和一个程序集文件。程序集文件定义了一个名为 add
的 C++ 函数。我使用的是 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
生成文件
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;
}
非常感谢任何帮助。谢谢!
在 OS/X 上,C 调用约定是函数在从对象导出时必须带有下划线(除非它被覆盖)以便C 可见。当你把 extern "C"
放在这个原型上时,你是说 add 使用 C 调用约定:
extern "C" int add(int a, int b);
这实际上是正确的,但是为了使您的汇编代码符合要求,您还需要确保您的汇编函数将是全局的并且对 C/C++ 可见 代码有一个前导下划线。您的汇编代码将像这样开始:
global _add
segment .text
_add:
您遇到的另一个问题是 Makefile
以及从 main.cpp
生成 main.o
的方式。
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
不知道。
我正在尝试 link 一个 C++ 文件和一个程序集文件。程序集文件定义了一个名为 add
的 C++ 函数。我使用的是 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
生成文件
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;
}
非常感谢任何帮助。谢谢!
在 OS/X 上,C 调用约定是函数在从对象导出时必须带有下划线(除非它被覆盖)以便C 可见。当你把 extern "C"
放在这个原型上时,你是说 add 使用 C 调用约定:
extern "C" int add(int a, int b);
这实际上是正确的,但是为了使您的汇编代码符合要求,您还需要确保您的汇编函数将是全局的并且对 C/C++ 可见 代码有一个前导下划线。您的汇编代码将像这样开始:
global _add
segment .text
_add:
您遇到的另一个问题是 Makefile
以及从 main.cpp
生成 main.o
的方式。
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
不知道。