I am attempting to call an assembly function from C++, and the linker is saying that the function I am trying to call does not exist. Here is the error:
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
Here is my source:
//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);
}
In case this helps, here is the disassembly of the files after I compiled them into object files:
Here is 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
Here is hello.o:
00000000 <hello>:
0: 08 95 ret
I've been searching for a few hours now, and I really have no idea whats going on.
Each file compiles individually, its just the linking that I believe screws up.
I can also compile pure assembly without any problem.
Any help would be appreciated, I just started looking into mixing Assembly and C++ for AVR.
Try this: in main.cpp,
extern "C" void hello(char, char, char, char, char);
With a "C"
in it. C++ changes the name of the function to include its type, which is called name mangling. The "C" tells the compiler not to mangle. The assembler doesn't mangle, so the compiler needs to know not to.
Incidentally, the mangling is how the linker is able to tell you the parameter types of the hello
it is looking for.
Edit Do strings main.o |grep hello
on your current object file and you will see a reference to hello with all sorts of funny characters after it. That is the mangled name.