Так вся соль в том, что перемещаемый код генерится автоматически, без лишних настроек. Проблемы могут быть только с вызовами подпрограмм - они вызываются по абсолютным адресам, так что их надо править. Но эта проблема решается через #define.
Я так делал несколько загрузчиков. Наиболее сложный - прием по UART пакетов по 32 байта (+ обрамление и контрольные суммы), проверка их на CRC-32, запись во флеш и посылка ответов (тоже с CRC-32). Все написано на Си (IAR 1.26A) без использования ассемблера. Уместилось в 2К ОЗУ F149.
В ОЗУ лежат таблицы для CRC32 (1 кбайт), буфер пакета (около 40 байт), аккумулятор для CRC32 (4 байта), п/п подсчета CRC32 и собственно обработчик пакетов с программатором.
Вся хитрость - правильно описать переменные и подпрограммы:
#define ram_crc32tab ((unsigned long *)(0x0200)) #define ram_ub (*(T_UART *)(0x0600)) #define ram_crc32 *(unsigned long *)(0x0600 + sizeof (T_UART)) #define a_ram_UpdateCrc32 (0x0600 + sizeof (T_UART) + sizeof (unsigned long)) typedef void (*vfc)(unsigned char c); #define ram_UpdateCrc32(c) (*(vfc)(a_ram_UpdateCrc32))(c)И дальше можно обращаться к переменным и подпрограммам обычным образом. Если пользуешься другим компилятором - внимательно посмотри ассемблерный текст, который он генерит.