AVR-GCC не связывает C++ с функцией сборки

Я пытаюсь вызвать функцию сборки из 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

Вот привет.о:

00000000 <hello>:
   0:   08 95           ret

Я искал несколько часов, и я действительно понятия не имею, что происходит.

Каждый файл компилируется индивидуально, я считаю, что это просто ссылка, которая облажалась.

Я также могу без проблем скомпилировать чистую сборку.

Любая помощь будет оценена по достоинству, я только начал изучать смешивание ассемблера и C++ для AVR.


person Sock314    schedule 08.10.2016    source источник
comment
objdump -dr покажет перемещения, поэтому вы увидите имя символа, которое на самом деле использует инструкция CALL. objdump -dC разберет вам имена. Не то, что вы хотите в этом случае, чтобы обнаружить проблему, но я обычно использую objdump -drwC.   -  person Peter Cordes    schedule 08.10.2016


Ответы (1)


Попробуйте это: в main.cpp,

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

С "C" в нем. C++ изменяет имя функции, чтобы включить ее тип, что называется изменением имени. «C» говорит компилятору не калечить. Ассемблер не искажает, поэтому компилятор должен знать, что этого делать нельзя.

Между прочим, искажение - это то, как компоновщик может сообщить вам типы параметров hello, которые он ищет.

Редактировать Выполните strings main.o |grep hello в текущем объектном файле, и вы увидите ссылку на приветствие со всевозможными забавными символами после нее. Это искаженное имя.

person cxw    schedule 08.10.2016
comment
лучше сделайте nm main.o, чтобы увидеть искаженное имя. - person fuz; 08.10.2016
comment
вы также можете сгруппировать несколько определений прототипов, используя extern "C" { placing all your definitions here within braces... }. Это отлично подходит для ваших заголовочных файлов. - person CRG; 21.07.2017