2016-10-08 54 views
1

我試圖從C++調用匯編函數,並且鏈接器說我試圖調用的函數不存在。以下是錯誤:AVR-GCC未將C++與彙編函數進行鏈接

avr-gcc -mmcu=atmega328 -Wall -o main.elf hello.S main.cpp 
/tmp/ccS7uaAX.o: In function `main': 
main.cpp:(.text+0x14): undefined reference to `hello(char, char, char, char, char)' 
collect2: error: ld returned 1 exit status 

這裏是我的源:

//Somewhere in hello.S 

.global hello 
hello: 
    ret 

//In main.cpp 

extern void hello(char, char, char, char, char); 

int main(){ 
    hello(1, 2, 3, 4, 5); 
} 

萬一這會有所幫助,這裏是文件的拆卸後,我將它們編成目標文件:

這裏main.o:

00000000 <main>: 
    0: 0f 93   push r16 
    2: cf 93   push r28 
    4: df 93   push r29 
    6: cd b7   in r28, 0x3d ; 61 
    8: de b7   in r29, 0x3e ; 62 
    a: 05 e0   ldi r16, 0x05 ; 5 
    c: 24 e0   ldi r18, 0x04 ; 4 
    e: 43 e0   ldi r20, 0x03 ; 3 
    10: 62 e0   ldi r22, 0x02 ; 2 
    12: 81 e0   ldi r24, 0x01 ; 1 
    14: 0e 94 00 00  call 0 ; 0x0 <main> 
    18: 80 e0   ldi r24, 0x00 ; 0 
    1a: 90 e0   ldi r25, 0x00 ; 0 
    1c: df 91   pop r29 
    1e: cf 91   pop r28 
    20: 0f 91   pop r16 
    22: 08 95   ret 

這裏是hello.o:

00000000 <hello>: 
    0: 08 95   ret 

我一直在尋找幾個小時,我真的不知道發生了什麼事。

每個文件單獨編譯,它只是我相信連接的螺絲。

我也可以編譯純粹的程序集沒有任何問題。

任何幫助將不勝感激,我剛開始考慮混合Assembly和C++ AVR。

+1

'objdump -dr'將顯示重定位,所以您會看到CALL指令實際使用的符號名稱。 'objdump -dC'會爲你取消名字。不是你想在這種情況下檢測到問題,但我通常使用'objdump -drwC'。 –

回答

3

試試這個:在main.cpp中,

extern "C" void hello(char, char, char, char, char); 

隨着它"C"。 C++更改函數的名稱以包含它的類型,稱爲名稱修改。 「C」告訴編譯器不要破壞。彙編器不會破壞,所以編譯器需要知道不需要。

順便提一下,鏈接器能夠告訴你它正在查找的hello的參數類型。

編輯對你當前的目標文件執行strings main.o |grep hello,你會看到其後的各種有趣的字符引用hello。這是一個錯位的名字。

+1

最好用'nm main.o'來查看被破壞的名字。 – fuz

+0

你也可以使用'extern「C」{將所有的定義放在大括號內}對多個原型定義進行分組...}'這對你的頭文件非常有用。 – CRG