|
|||||||
Как в языке Си вызвать функцию, для которой известен адрес вызова в виде числа
Время создания: 17.02.2022 17:12
Автор: intrea
Текстовые метки: язык, Си, C, адрес, функция, вызвать, embedding, машинный код
Раздел: Компьютер - Программирование - Язык C (Си)
Запись: xintrea/mytetra_syncro/master/base/1645107136euxp0gl4ty/text.html на raw.github.com
|
|||||||
|
|||||||
В эмбеддинг-разработке может встретиться следующая задача: имея адрес функции в виде обычного числа, надо вызвать функцию по данному адресу. В простейшем случае предполагается, что функция не имеет аргументов, и ничего не возвращает. Организация вызова функци может выглядеть следующим образом:
Что здесь происходит? Перед прототипом функции jump_to_funct прописан атрибут naked, благодаря которому компилятор для данной функции не будет создавать пролог и эпилог. То есть, код данной функции будет содержать только команды, которые получатся в результате компиляции строки 4 и 5. В функцию jump_to_func передаются два числа. Первое число - это адрес вершины стека. Второе число - это адрес функции, т. е. адрес первой машинной команды вызываемой функции. На строке 4 происходит вызов инстрикт-функции __set_MSP(stack). Данная функция установит указатель стека на значение, переданное в переменной stack. Пременная stack содержит адрес в виде беззнакового целочислоительного числа. В строке 5 происходит вызов функции, расположенной по адресу func, причем этот адрес так же задается просто в виде беззнакового целочислительного числа. По идее, если нужно сделать простой вызов функции без смены адреса вершины стека, строку 4 можно не писать. Проинициализировать значения stack и func можно следующим образом: void main_start() { uint32_t *boot_from = (uint32_t*)MAIN_RUN_FROM; if (((boot_from[0] >> 24) != (SRAM_BASE >> 24)) && ((boot_from[0] >> 24) != (CCMDATARAM_BASE >> 24))) return send_str("SRAM ERROR\r"); if (((boot_from[1] >> 24) != (FLASH_BASE >> 24)) && (boot_from[1] > MAIN_RUN_FROM)) return send_str("FLASH ERROR\r"); send_str("CONTEXT OK\r\r");
usart_deinit(); RCC_DeInit(); jump_to_func(boot_from[0], boot_from[1]); } В данном случае предполагается, что данный код вызывается до функции main(). По-сути, данный код вызывает функцию main() по указанному адресу. Полный код похожего проекта можно посмотреть на GitHub: https://github.com/Mirn/Boot_F4_fast_uart/blob/master/src/sfu_commands.c |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|