[英]Undefined symbols for architecture arm64 when compiling c++ and assembly code on MacOS
我正在閱讀這本書的 ARM64 程序集,有一章你必須從 c++ 調用匯編代碼。
每次我編譯它我都會收到這個錯誤
Undefined symbols for architecture arm64:
"_IntegerAddSubA_", referenced from:
_main in main-11e536.o
"_IntegerAddSubB_", referenced from:
_main in main-11e536.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
主.cpp
#include <iostream>
using namespace std;
extern "C" int IntegerAddSubA_(int a, int b, int c);
extern "C" long IntegerAddSubB_(long a, long b, long c);
template <typename T>
void PrintResult(const char* msg, T a, T b, T c, T result){
const char nl = '\n';
cout << msg << nl;
cout << "a" << a << nl;
cout << "b" << b << nl;
cout << "c" << c << nl;
cout << "result (a + b + c) = " << result << nl;
cout << nl;
}
int main(int argc, const char * argv[]) {
int a1 = 100, b1 = 200, c1 = -50, result1;
result1 = IntegerAddSubA_(a1, b1, c1);
PrintResult("IntergerAddSubA_", a1, b1, c1, result1);
long a2 = 1000, b2 = -2000, c2 = 500, result2;
result2 = IntegerAddSubB_(a2, b2, c2);
PrintResult("IntegerAddSubB_", a2, b2, c2, result2);
return 0;
}
CH.S
.text
.global IntegerAddSubA_
.align 2
IntegerAddSubA_:
add W3,W0,W1
sub W0,W3,W2
ret
.global IntegerAddSubB_
IntegerAddSubB_:
add X3,X0,X1
sub X0,X3,X2
ret
我嘗試先將匯編代碼編譯成一個 object 文件,但似乎沒有任何效果。
如前所述,您必須將前導“_”添加到程序集文件中的符號名稱。 這只是您對 C 語言的實現在 ARM64 上(在體系結構和操作系統的各種組合上)所做的事情。
最好避免匯編源代碼的另一個原因。 通過像這樣使用內聯 asm 可以大大改進代碼:
int IntegerAddSubA_(int a, int b, int c) {
int r, t;
asm("add %w[t], %w[a], %w[b]\n"
"sub %w[r], %w[t], %w[c]"
: [r] "=r" (r), [t] "=&r" (t)
: [a] "%r" (a), [b] "r" (b), [c] "r" (c)
: );
return r;
}
Output 操作數: r
是最終結果,可能與輸入重疊。 t
也被寫入並且可能不會與任何輸入寄存器重疊。
輸入操作數:對於 ARM64 上的所有重要事項, a
與b
可交換( a+b
== b+a
)。
Clobber:什么都沒有被破壞。 Memory 沒有改變。
編譯成這個:
IntegerAddSubA_(int, int, int): // @IntegerAddSubA_(int, int, int)
add w8, w0, w1
sub w0, w8, w2
ret
最大的區別是編譯器將內聯此代碼,然后選擇可用的或已經保存值的寄存器。 它避免了為一些簡單的事情(例如一些 asm 指令)而不得不洗牌寄存器和進行昂貴的 function 調用。
我建議僅在具有復雜功能時才使用匯編源文件。
int foo(int a1, int b1, int c1, int a2, int b2, int c2) {
return IntegerAddSubA_(a1, b1, c1) + IntegerAddSubA_(a2, b2, c2);
}
foo(int, int, int, int, int, int): // @foo(int, int, int, int, int, int)
add w9, w0, w1
sub w8, w9, w2
add w10, w3, w4
sub w9, w10, w5
add w0, w9, w8
ret
請注意 IntegerAddSubA_ 的 2 個內聯版本如何使用 arguments 已經存在的寄存器並使用不同的臨時和結果寄存器,從而不會浪費操作碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.