Вопрос уже обсуждался в
http://electronix.ru/forum/lofiversion/index.php/t19767.htmlОт себя могу добавить, что вначале стоит прочитать "AVR034 Mixing C and Assembly Code with.pdf".
Далее нужно создать модуль с расширением *.asm и подключить его у проекту.
Пример модуля обработчика прерываний:
NAME UART_int ; имя
#include "ioavr.h" ; главное не подключать модули, в которых определены C-шные объекты
COMMON INTVEC(1) ; размещаем код в Interrupt Vector Segment
ORG USART_RXC_vect ; по адресу обработчика прерывания
rjmp USART_RXC ; переход на сам обработчик
extern uartRxError, uartESCReceived ; введение переменных, объявленных в другом модуле
RSEG CODE ; размешение программы в сегменте основного кода (RSEG)
USART_RXC:
call SAVE_DATA ; не забываем сохранить используемые регистры
;
; собственно исполняемый код
;
jmp EXIT_INT ; восстанавливаем значения регистров и выходим из прерывания
EXIT_INT:
call RESTORE_DATA
reti
SAVE_DATA:
st -Y, R16
in R16, SREG ; обязательно сохраняем флаги
st -Y, R16
st -Y, R17
ret
RESTORE_DATA:
ld R17, Y+
ld R16, Y+
out SREG, R16 ; восстанавливаем флаги
ld R16, Y+
ret
END
В C-модулях ничего делать не надо.
Если нужно из C-кода вызывать ASM-функции, то после перечитывания топиков "Passing Variables Between C and Assembly Code Functions" и "Calling Assembly Code Functions from a C Program". В C-модулях через extern объявляем вызываемую функцию и вызываем как обычно, а в AMS-модуле ее шарим через PUBLIC:
NAME get_port
#include "ioavr.h"
PUBLIC get_port ; Declare symbols to be exported to C function
RSEG CODE ; This code is relocatable, RSEG
get_port; ; Label, start execution here
in R16,PIND ; Read in the pind value
swap R16 ; Swap the upper and lower nibble
out PORTB,R16 ; Output the data to the port register
ret ; Return to the main function
END