2009-06-05 8 views
3

私はコースプロジェクトのためにリアルタイム操作システムを最初から書いています。スタック領域に空きメモリを使用する予定で、既存のコードを上書きしないようにする必要があるため、チップにダウンロードした後で自分のコードの最終アドレスを知りたいと思います。私のコードの最終アドレスを取り出す方法

GCCの提供する変数__endについては、コードの終わりですが、__endの意味とコードの使い方についてはわかりません。誰もそれを少し説明したり、いくつかの資料へのリンクを提供することができますか?

ありがとうございます。

+0

あなたはLinuxを使用していますか? – toto

+0

可能性があります埋め込み – Gerhard

答えて

-2

まあ、私はGCCとのその慣れていないんだけど、多分あなたはこのような何か行うことができます。

long foo() 
{ 
    int anything[0]; 
    return *(&anything - 1); 
} 

long endOfProgram() 
{ 
    return stackPointer(); 
} 

を私はここでやろうとしていることである:

  1. コールendOfProgram()
  2. endOfProgramはfooを呼び出すため、endOfProgramのアドレスがスタックにプッシュされます。
  3. fooのスタックに何か[0]をプッシュします。
  4. endOfProgramのメモリ位置であるべきもののアドレスの直前にある要素の位置を取得します。

私の構文のいくつかは間違っているかもしれませんが、私がしようとしていることの要点を得ることができれば幸いです。

EDIT:

...またはちょうどendOfProgramへの関数ポインタの値をつかみます。私はそれも働くだろうと思う。

+0

これは、現在のスタックポインタの場所の近くで何かを取得します。コードセグメントの終わりは得られません。 –

+0

まあ、私はあなたのコードの最後にendOfProgramを置くと、それは間違った前提かもしれない、最後に置かれるだろうと仮定していました。 – CookieOfFortune

+0

これは、現在の翻訳単位の最後にアドレスを与えるかもしれません(または、オプティマイザが機能を動かす場合はそうではないかもしれませんが)。複数のソースファイルから複数の翻訳単位が来る場合は機能しません。また、どの翻訳単位が最後にリンクされるのかを知る必要があります。 –

2

リンカースクリプトを使用できます。あなたのCコードでは、宣言:

// call this whatever you want; the linker will fill this in with the address 
// of the end of code 
extern uint32_t endOfCode; 

次に、あなたのリンカスクリプトでは、すぐに.textセクションの定義の後に以下を追加します。私は、リンカスクリプトに精通していないよ

PROVIDE(endOfCode = .); 

、私は完全で実用的な例を提供することはできません。上記のようにデフォルトのリンカースクリプト(私はどのように入手できないか分かりません)をとり、それを変更してから、リンカーの-Tオプションを使用して指定しなければなりません。がんばろう!

3

アダムローゼンフェルドが指摘するように、あなたは正確に正しい場所に位置していますあなたのための1つまたは複数のシンボルを定義するために、リンカ制御ファイルを使用する必要があります。

gccとbinutilsについては、ldのリンカスクリプト構文を使用します。私がここで省略しているすべての詳細については、ldのマニュアルを参照してください。それは不透明ですが、埋め込まれた世界で多大な労力を費やすつもりなら、しばらく時間を費やすべきです。それはあなたのために報われるでしょう。

リンカースクリプトでは、.textセグメントの前と1つ後にシンボルを定義する必要があります。

アダムはPROVIDE()の構文を使用しています。しかし、あなたの名前が一意であることを保証できるなら、PROVIDEで定義をラップする必要はありません。これは、あなたができることが保証されているか、後で多くの混乱を招く恐れがあることに注意してください。私たちは、SDRAMコントローラは、SDRAMメモリをマッピングすることを決めた場所に(この場合は)意味し、一定のアドレスにシンボルを定義するために

__SDRAM_CS1 = 0x10000000; 

:私のスクリプトで

、私は同じようなものを使用しますCIでは、次のように宣言します。

したがって、SDRAMが実際にどこにあるかを知る必要があるコードで使用できるように宣言します。

の.textセグメントの終わりを見つけるのシンボルに対しては、リンカスクリプトで次の

SECTIONS 
{ 
    ... 
    .text { 
     _start_text = .; 
     *(.text); 
     ... 
     _end_text = .; 
    } 
    ... 
} 

のようなものを持っているでしょうし、中

extern unsigned char _start_text[]; 
extern unsigned char _end_text[]; 

として開始と終了のシンボルを宣言しますその後、開始アドレスは単に_start_textであり、テキストセグメントのバイト長は_end_text - _start_textです。

私は多くの細部を省いたことに注意してください。 .text以外の名前のセクションは、テキストセグメント内にあるかのように扱わなければならないでしょう。主な例は、読み取り専用のデータです。これは、テキスト部分に安全に置かれることがあります。その理由は、constであることが知られています。組み込みシステムでは、必要がない場合は貴重なRAMにコピーしないでください。また、データセグメントの初期化子、およびグローバルに生成されたオブジェクトのコンストラクタの内部生成リストは、すべてテキストセグメントの近くに配置されます。

画像サイズにこのようなものを含めるかどうかは、それらが使用されていることを理解した後に行う必要がある設計上の決定です。

+0

私の場合は、コンパイルするために、Cコードで_を残す必要がありました(リンカースクリプトに残しておきます)。私はgcc 4.6(MinGW)を使用しています。 も参照してください。http://cygwin.com/ml/binutils/2007-07/msg00155.html – rbeede

+0

一部の実装では、Cシンボルがオブジェクトファイルへの途中でアンダースコアを大きくすることは珍しくありません。これが起こるかどうかを制御するコンパイラフラグがあります。リンカースクリプトは自然に最も生の形のシンボルを扱います。この規約では、Cから参照できないアセンブリ言語ファイルでシンボルを定義することができます。これは、使用可能なツールチェーンを作成する際に役立ちます。 – RBerteig

0

最後にそれを置くのではなく、大きな静的配列を宣言してそれを使用することもできますし、派手なコンパイラやリンカのトリックは使用できませんか?

+0

埋め込みコードの場合、ほとんどの場合、ソースキットの一部としてリンカスクリプトを処理する必要があります。もちろん、完全なOSの下でのユーザの土地の状況は異なります。 – RBerteig

関連する問題