#c #assembly #arm #inline-assembly #cortex-m
Вопрос:
С помощью gcc/clang для коры головного мозга ARM M можно ли передать адрес функции в качестве константы в инструкциях ассемблера с операндами выражения C ? Точнее, я хотел бы загрузить R12 с адресом функции (сохраненным в памяти): ldr R12, =func
в функции C, например, такой пример
// __attribute__((naked))
int loader(int fn)
{
__asm ("ldr R12, =%0"::??? (fn):"r12");
// ... then SVC #0, and the R0 is the return value
}
Вопрос в том, что именно я должен указать для входного операнда?
ПРАВКА: Спасибо за комментарии! На самом деле мне нужно повторно реализовать KEIL __svc_indirect(0)
, который загружает R12 с адресом функции и передает до четырех аргументов в R0..R3 (см. __svc_косвенный
Комментарии:
1. Есть ли какая-то причина, по которой вы просто не запрашиваете адрес функции в реестре в первую очередь? Например
(void*)fn
, указать свойint
указатель или просто запросить int в регистре, например"r"(fn)
. Вы можете использоватьregister int fn asm("r12")
, чтобы ограничение «r» выбрало r12. Как вы хотите, чтобы ваш код компилировался? Как будто вы хотите, чтобы это встроилось в какой-то вызывающий объект, такint fn
что это может быть константа времени связи, которую компилятор может встроить в инструкцию с помощью имени символа? Но голые функции не могут встроиться.2. Обратите внимание, что
naked
функции не могут безопасно использовать расширенный Asm, только базовый (без ограничений/операндов). И их нужно вернуть вручную (например, закончитьbx lr
) gcc.gnu.org/onlinedocs/gcc/…3. не стервозная функция, возвращающая
int
значение, должна что-то внести вr0
реестр…4. @peter-cordes, мне нужно повторно реализовать __svc_косвенный(0) КЕЙЛА, который загружает R12 с адресом функции и передает до четырех аргументов в R0..R3
5. Хорошо, тогда вы должны использовать
"r"
ограничение, чтобы GCC сделалldr
это за вас (сregister ... asm("r12")
переменной). И не создавайтеnaked
функцию; это в основном эквивалентно использованию отдельного.s
файла, за исключением искажения имени.
Ответ №1:
Используйте i
ограничение и вручную добавьте =
символ:
__asm ("ldr r12, =%0" :: "i"(fn) : "r12");
Обратите внимание, что инструкция встроенной сборки по-прежнему неверна по другим причинам, некоторые из которых были указаны в комментариях к вашему вопросу. Также рассмотрите возможность использования переменной с ограничением по регистру для такого рода вещей:
register int fn asm("r12");
__asm ("" :: "r"(fn));