Search code examples
cassemblylinkeravr

How can I call assembly function from C code?


I use avr-as assembler. I want to use functions defined in assembly from a C file. How can I use assembly code in C code?

I am looking for solutions where the assembly source is in a separate source, i.e. not inlined into the C source.


Solution

  • Here's a simple example to get you started. Suppose you want to write a main loop in C and you want to call a function written in assembly to blink PB5.

    The C source declares and uses (but doesn't define) blinkPB5:

    /* main.c */
    #include <avr/io.h>
    #include <util/delay.h>
    
    extern void blinkPB5();
    
    int main ()
    {
        DDRB |= _BV(DDB0);
    
        for (;;)
        {
            blinkPB5();
            _delay_ms(500);
        }
    }
    

    The assembly source defines blinkPB5. Note that .global is used to export blinkPB5:

    ;; blinkPB5.s
    .global blinkPB5
    
    .section .text
    
    blinkPB5:       
            ldi r25, 0x01
            in  r24, 0x05
            eor r24, r25
            out 0x05, r24
            ret
    
    .end        
    

    The two can be compiled separately:

    avr-gcc -c -O3 -w -mmcu=atmega328p -DF_CPU=1000000L main.c -o _build/main.c.o
    avr-gcc -c -O3 -w -mmcu=atmega328p -DF_CPU=1000000L blinkPB5.s -o _build/blinkPB5.s.o
    

    then linked together, and formatted into a .hex image:

    avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p _build/main.c.o _build/blinkPB5.s.o -o _build/image.elf
    avr-objcopy -Oihex -R.eeprom _build/image.elf _build/image.hex