Search code examples
c++assemblyavr-gcc

AVR-GCC Not Linking C++ with Assembly Function


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.


Solution

  • 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.