Контекст:
Я работаю над целью ARM, точнее, микроконтроллером Cortex-M4F от ST. При работе на таких платформах (микроконтроллерах в целом), очевидно, нет ОС; для того, чтобы получить рабочую среду C/С++ (более того, чтобы быть стандартно совместимым в отношении инициализации переменных), должен быть какой-то код запуска, запущенный на reset, который выполняет минимальную настройку, прежде чем явно называть main
. Такой код запуска, как я намекал, должен инициализировать инициализированные глобальные и статические переменные (например, int foo = 42;
в глобальной области) и отключать другие глобальные переменные (например, int bar;
в глобальной области). Затем, если необходимо, вызываются глобальные "ctors".
На микроконтроллере это просто означает, что код запуска должен копировать данные из flash в ram для каждого инициализированного глобального (все в разделе ".data" ) и очищать остальные (все в ".bss" ). Поскольку я использую GCC, я должен предоставить такой код запуска, и я с радостью проанализировал несколько кодов запуска (и связанный с ним компоновщик script!) В комплекте с многочисленными примерами, которые я нашел в Интернете, все с использованием той же демонстрационной доски, что и я развивается дальше.
Вопрос:
Как уже было сказано, я видел множество кодов запуска, и они инициализируют глобальные перемены по-разному, некоторые более эффективные с точки зрения пространства и времени, чем другие. Но у всех их есть что-то странное: они не использовали memset
и memcpy
, вместо этого применяя ручные пилы для выполнения задания. Поскольку мне кажется естественным использовать стандартные функции, когда это возможно (простой "СУХОЙ принцип" ), я попробовал следующее вместо начальных рукописных циклов:
/* Initialize .data section */
ldr r0, DATA_LOAD
ldr r1, DATA_START
ldr r2, DATA_SIZE
bl memcpy /* memcpy(DATA_LOAD, DATA_START, DATA_SIZE); */
/* Initialize .bss section */
ldr r0, BSS_START
mov r1, #0
ldr r2, BSS_SIZE
bl memset /* memset(BSS_START, 0, BSS_SIZE); */
... и он работал отлично. Экономия пространства пренебрежимо мала, но теперь он явно мертв.
Итак, я подумал об этом, и в этом случае я не вижу причин делать рукописные петли:
-
memcpy
иmemset
, скорее всего, будут связаны в исполняемом файле, так как программист будет использовать его напрямую или косвенно через другую библиотеку; - Он меньше;
- Скорость не является очень важным фактором для кода запуска, но, тем не менее, она скорее всего быстрее;
- Это почти невозможно, чтобы понять это неправильно.
Любая идея, почему бы не полагаться на memcpy
и memset
для кода запуска?