コンテキスト:
私はARMターゲット、より具体的にはSTのCortex-M4Fマイクロコントローラーに取り組んでいます。このようなプラットフォーム(一般的にはマイクロコントローラー)で作業する場合、明らかにOSはありません。動作するC/C ++「環境」を取得するには(さらに、変数の初期化に関して標準に準拠するため)、明示的に呼び出す前に必要な最小限のセットアップを実行する、リセット時に実行される何らかのスタートアップコードが必要ですmain
。私が示唆したように、このようなスタートアップコードは、初期化されたグローバル変数と静的変数(グローバルスコープなど)を初期化int foo = 42;
し、他のグローバル変数(グローバルスコープなど)をゼロにする必要がありますint bar;
。次に、必要に応じて、グローバルな「ctors」が呼び出されます。
マイクロコントローラーでは、これは単に、スタートアップコードが初期化されたグローバル(すべてセクション「.data」)ごとにフラッシュからRAMにデータをコピーし、他のグローバル(すべて「.bss」)をクリアする必要があることを意味します。私はGCCを使用しているので、そのようなスタートアップコードを提供する必要があり、インターネットで見つけた多数の例にバンドルされているいくつかのスタートアップコード(および関連するリンカースクリプト!)を、開発中の同じデモボードを使用して喜んで分析しました。 。
質問:
述べたように、私は多くのスタートアップコードを見てきました、そしてそれらは異なる方法でグローバルを初期化します、いくつかは他のものより空間と時間の点でより効率的です。しかし、それらにはすべて奇妙な共通点があります。それらは使用せmemset
ずmemcpy
、代わりに手書きのループを使用して作業を行いました。可能な場合は標準関数(単純な「DRY原理」)を使用するのが自然に思えるので、最初の手書きループの代わりに次のことを試しました。
/* 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