3

128KBのメモリ領域があると仮定します。リンカディレクティブでは、この領域を3つのセクションに分割しました。

  • .section_text
  • .section_data
  • .section_bss

各セクションのサイズはコンパイル前には不明ですが、.section_textと.section_dataが割り当てられた後、メモリ領域内の残りのすべてのスペースを使用するように.section_bssを制限しました。

.region_bssで使用可能なすべてのスペースを使用するC配列を宣言する方法はありますか?リージョン全体を安全に使用できるように、.region_bssを使用しているのはそれだけであると想定します。たとえば、目的はあるが明らかに間違っている:

char entire_bss[sizeof(.region_bss)];

これがいくつかの予想される反応に対する私の事前回答です。まず、sizeof()がこのように機能しないことを私は知っています。私はそれを使ってアイデアを広めています。次に、これはポインターではなく配列を使用して実行する必要があると想定します(ポインターを使用した解決は可能であり、かなり単純です)。第三に、.region_bssの開始アドレスと終了アドレスを取得できることは知っていますが、それらを使用して配列のサイズを決定する方法はわかりません。少なくとも、Cで機能する方法はありません。

これを行う方法はないかもしれませんが、そこにいる天才がそれを理解してくれることを願っています。Green Hillsツールセットで動作させることができる場合は、追加のクレジット。

4

5 に答える 5

2

通常、これを行う方法は次のようなものです。

extern char section_bss[];

コンパイラ、アセンブラ、およびリンカがそれが(または同様の名前)section_bssのエイリアスであることを認識できるように、いくつかの追加のものがスローされます。.section_bss

サイズを取得するには、bssの最後にあるシンボルに対して同じことを行い、違いを見つけたいと思うでしょう。

于 2010-09-21T21:00:40.443 に答える
2

で使用可能なすべてのスペースを使い果たすC配列を宣言する方法はあります.region_bssか?

簡単な答えは「いいえ」です。

GreenHillsがbinutilsでGNUツールチェーンを使用していて、リンカースクリプトをカスタマイズできる場合は、128Kブロックの終わりをマークするために使用する変数をアプリケーションの名前空間に追加できます。PROVIDE(このような変数にアクセスする方法の例をここで参照してください)。そのように固定サイズのC配列はありませんが、プログラムは配列の終わりを見つけることができるため、配列のサイズはCプログラムに一般的に十分です。

純粋なC99を使用してそれを達成したい場合は、標準でカバーされていないため、信頼性が非常に低いため、運が悪い可能性があります。

于 2010-09-21T21:27:05.730 に答える
2

いいえ、できません。理由も簡単に理解できます。コンパイル段階では、.bssと.dataの概念はありません。これらは、純粋なリンカーの規則です。コンパイラはいくつかの抽象的な概念(定数データ、静的データ、コード)を知っていますが、それらのリンカセクションへのマッピングは単なる慣例であり、リンカ、OS、プロセッサ、さらにはメモリモデルオプションによっても異なります。位置に依存しないコードを作成する場合、たとえば、定数はコードセグメントに配置されることがよくあります。組み込みプラットフォームでは、これらの問題に苦労することがあり、そのためにコーディングスタイルを調整する必要があります(MS-C 5.1コンパイラで構築された80186プロセッサをベースにしたモデルがあった場合、この.dataセクションを使用できませんでした) (グローバル、初期化された変数と静的)ツールチェーンがそれらをROMに配置するため。

ビルドプロセス全体の最後に生成されたバイナリにパッチを適用することで、同様の問題を一度解決しました。リンカによって生成されたマップファイルから別のセクションの使用済みメモリを抽出し(オプションで検索します)、指定されたモデル(256K、512K、および896Kモデルがありました)のメモリサイズからそれを差し引き、1つに設定しました。正しい値を持つグローバル定数の。したがって、このサイズへのすべての参照がこのグローバル変数を介して機能することが重要でした。このメモリプールは、malloc/の実装で使用されましたfree

于 2010-09-22T06:09:01.670 に答える
0

あなたがやろうとしていることは、プラットフォームに大きく依存します。最善の策は、配列をextern char the_array []、end_of_array[]として宣言することです。Cファイル内で、そしておそらくアセンブリ言語のソースファイル内で、the_arrayとend_of_arrayのいくつかのデータセクションを宣言します。次に、リンカーの仕様を調整して、the_arrayがボトムアップで割り当てられたものの最後になり、end_of_arrayがトップダウンで割り当てられたものの先頭になり、それらの間に他のものがないようにします。可能です-私はいくつかのプラットフォームでそれを行いました-しかし、リンカーのドキュメントを注意深く読んで、予期しないときにリンカーが物事を再配置しないようにすることが重要です。

于 2010-09-21T21:59:57.877 に答える
0

どうしたの

extern char __ghsbegin_region_bss[];
extern char __ghssize_region_bss[];
#define entire_bss __ghsbegin_region_bss
#define sizeof_entire_bss ((size_t)__ghssize_region_bss)

?この答えに満足できない理由が少なくとも1つ考えられますが、これにはC ++テンプレートメタプログラミングの魔法が関係しています(つまり、タイプのentire_bssサイズが適切でないため、サイズに依存するテンプレートの解決方法が異なります)。配列のサイズを何にも使用しない限り(Cではこれが当てはまります)、このアプローチで問題ありません。

__ghssize_region_bssこれはコンパイル時定数ではないことに注意してください—リンク時まで解決されません—したがって[...]、コンパイル時に配列型の内部にそれを取得する方法は100%ありません。

Green Hillsマニュアルの「節記号の開始、終了、およびサイズ」の章を参照してください。

于 2012-09-06T18:18:08.630 に答える