19

GNUを使用して、ARM Cortex-M3ベースのマイクロコントローラー(Thumb 2命令セット)のアセンブリプログラムに取り組んでいます。

いくつかのサンプルコードでは、のようなディレクティブを見つけ.sizeました。これはELFディレクティブであると理解しています.section.type例として:

    .section    .text.Reset_Handler
    .weak       Reset_Handler
    .type       Reset_Handler, %function  
Reset_Handler:
    bl      main
    b       Infinite_Loop    
    .size   Reset_Handler, .-Reset_Handler



ディレクティブは、シンボルのタイプを設定すると言われています。.type通常は、%object(データを意味しますか?)または%functionのいずれかになります。それがどのような違いを生むのかわかりません。必ずしも含まれているわけではないので、いつ使用する必要があるのか​​わかりません。

これに関連するのは.thumb_funcディレクティブです。私が読んだことから、それは以下と同等であるように思われます:

.thumb 
.type Symbol_Name, %function

それとも完全に違うものですか?



.sizeおそらくシンボルに関連付けられたサイズを設定します。これが必要なとき、私にはわかりません。これはデフォルトで計算されますが、このディレクティブでオーバーライドできますか?もしそうなら-いつオーバーライドしたいですか?



.sectionドキュメントを見つけるのは簡単で、それが何をするのかについてはかなりの考えがあると思いますが、それでも使用法については少しわかりません。text私の理解では、さまざまなELFセクション(コード、data書き込み可能データ、bss初期化されていないデータ、定数など)を切り替え、rodata必要に応じて新しいセクションを定義します。コード、データ、初期化されていないデータなどを定義するかどうかに応じて、これらを切り替えると思います。しかし、上記の例のように、なぜ関数のサブセクションを作成するのでしょうか。


これに関するどんな助けもありがたいです。これをより詳細に説明するチュートリアルまたはドキュメントへのリンクを見つけることができれば(できれば初心者には理解できるでしょう)、私は非常に感謝しています。

これまでのところ、「マニュアルとしての使用」はある程度役に立ちました。おそらく、より多くの知識があれば、私よりも多くのことを学ぶことができます。

4

3 に答える 3

15

私は何年にもわたって多くのアセンブラでアーム/サムをプログラミングしてきましたが、そこにある多くのディレクティブのほとんどを必要としませんでした。

.thumb_func は、別のレスポンダーが指摘したように非常に重要です。

例えば

.globl _start
_始める:
    bリセット

リセット:

。腕

.globl 1
1:
    r0、r0、#1 を追加
    bx lr

。親指

.globl 2
2:
    r0、r0、#2 を追加
    bx lr

.thumb_func
.globl 3
三:
    r0、r0、#3 を追加
    bx lr


.単語 2
.単語 3

.arm または以前は .code32 または .code 32 のようなものであったため、これは親指コードではなく腕のコードであり、cortex-m3 では使用する必要はありません。

.thumb 同様に、以前は .code 16 であったか、またはそれがまだ機能している可能性があります。同じ取引により、次のコードの親指がアームではなくなります。

使用しているラベルが、他のファイルから、または間接的に分岐する必要があるグローバル ラベルでない場合、.thumb_func は必要ありません。しかし、これらのグローバル ラベルの 1 つへの分岐のアドレスを適切に計算するには (lsbit は親指の場合は 1 で、腕の場合は 0 です)、それを親指または腕のラベルとしてマークし、thumb_func でそれを行います。コードを追加して分岐する前にそのビットを設定する必要があり、ラベルは C から呼び出すことができません。

00000000 <_start>:
   0: eaffffff b 4 <1>

00000004 <1>:
   4: e2800001 追加 r0、r0、#1
   8: e12fff1e bx lr

0000000c <2>:
   c: 3002 は、r0、#2 を追加します
   e: 4770 bx lr

00000010 <3>:
  10: 3003 は r0、#3 を追加します
  12: 4770bxlr
  14: 0000000c andeq r0, r0, ip
  18: 00000011 andeq r0, r0, r1, lsl r0

.thumb までは、アセンブラは必要に応じてアーム コードです。

2 番目と 3 番目のラベル/関数の両方が必要なサム コードですが、2 番目のラベルには偶数番号のアドレスがあり、3 番目のラベルには適切な奇数番号のアドレスがあります。

最新の codesourcery ツールを使用して、上記のサンプルをアセンブル、リンク、およびダンプしました。

すべてがthumb(/thumb2)であるcortex-m3では、thumb_funcはそれほど重要ではないかもしれません.コマンドラインスイッチで動作するだけかもしれません. 親指のみのプロセッサから通常のアーム/親指コアに移行する場合に備えて、これは良い習慣です。

一般に、アセンブラーは、これらすべてのディレクティブを追加したり、物事を高水準言語のように見せたり感じたりする他の方法を追加することを好みます。それらを使用する必要はないと言っているだけです。私はアーム用のアセンブラを切り替え、多くの異なるプロセッサ用に多くの異なるアセンブラを使用し、より少ないアプローチを好みます。つまり、アセンブリ自体に焦点を当て、ツール固有のアイテムをできるだけ少なく使用することを意味します. ただし、私は通常、ルールではなく例外であるため、コンパイラ出力が生成するディレクティブを調べることで、より頻繁に使用されるディレクティブを把握できます (ドキュメントで確認します)。

unsigned int one ( unsigned int x )
{
    戻ります(x+1);
}


    .arch armv5te
    .fpu ソフト vfp
    .eabi_attribute 20、1
    .eabi_attribute 21, 1
    .eabi_attribute 23、3
    .eabi_attribute 24, 1
    .eabi_attribute 25, 1
    .eabi_attribute 26, 2
    .eabi_attribute 30、2
    .eabi_attribute 18、4
    .file "bob.c"
    。文章
    .align 2
    .グローバルなもの
    .type one, %function
1:
    .fnstart
.LFB0:
    @引数= 0、ふり= 0、フレーム= 0
    @ frame_needed = 0, uses_anonymous_args = 0
    @リンク登録保存を廃止。
    r0、r0、#1 を追加
    bx lr
    .fnend
    .size one, .-one
    .ident "GCC: (Sourcery G++ Lite 2010.09-50) 4.5.1"
    .section .note.GNU-stack,"",%progbits

.align を使用するのは、アームとサム アセンブラ、またはデータをアセンブラと混合する場合です。このようなプラットフォームのアセンブラは、サム命令がハーフワード境界にあり、アーム命令がワード境界に位置合わせされているなど、明らかなことを認識していると思われます。ツールは必ずしもそれほどスマートではありません。.aligns をまき散らしても害はありません。

.text はデフォルトであるため、少し冗長ですが、害はありません。.text と .data は標準の属性です (arm に固有のものではありません) ターゲットで rom と ram の組み合わせをコンパイルする場合、気にするかもしれません (リンカー スクリプトで何をするかによって異なります)。 .

.size 明らかに関数のサイズは、そのディレクティブから始まります。アセンブラはこれを独自に把握することはできないため、この関数のサイズがコード、リンカ スクリプト、デバッガ、ローダーなどにとって重要な場合は、これを正しくする必要があります。それ以外の場合は、気にする必要はありません。関数は高レベルの概念ですが、アセンブラーには実際には関数がなく、サイズを宣言する必要はありません。そして、Cコンパイラは確かに気にしません。分岐先のラベルを探しているだけで、アームファミリの場合、分岐先のサムコードまたはアームコードです。

長いコードで即値 (ldr rx,=0x12345678) を処理するのが面倒な場合は、.pool ディレクティブ (より新しい同等のものがあります) が便利です。ここでもまた、このデータを無条件分岐の後に配置するほどツールが常にスマートであるとは限りません。私は怠惰な半分真剣に言います。label: .word のことを常に行うのは苦痛であり、arm ツールと gcc ツールの両方でそのショートカットが許可されていると信じているため、他の人と同じように使用しています。

また、llvm は追加の .eabi_attribute を 1 つまたは 2 つ出力します。これは、コード ソースのバージョン/mods でサポートされているが、gnu でリリースされた binutils ではサポートされていません (おそらくまだ)。動作する 2 つの解決策は、llvm の asm print 関数を変更して eabi_attributes を書き込まないようにするか、少なくともコメント (@) を付けて書き込むか、コード ソースから binutils source/mods を取得してそのように binutils をビルドすることです。コード ソースは gnu (たとえば、thumb2 のサポート) をリードしたり、新しい機能をバックポートしたりする傾向があるため、これらの llvm 属性はメインラインの binutils に間もなく存在すると思います。llvm コンパイル済みコードから eabi_attributes を削除しても、悪影響はありませんでした。

上記の同じ関数の llvm 出力は次のとおりです。これは明らかに、eabi_attributes をコメントアウトするために変更した llc です。

    .syntax 統一
@ .eabi_attribute 20, 1
@ .eabi_attribute 21, 1
@ .eabi_attribute 23, 3
@ .eabi_attribute 24, 1
@ .eabi_attribute 25, 1
@ .eabi_attribute 44、1
    .file "bob.bc"
    。文章
    .globl 1
    .align 2
    .type one,%function
1つ: @ @1つ
@ BB#0: @ %entry
    r0、r0、#1 を追加
    bx lr
.Ltmp0:
    .size one、.Ltmp0-one

elf ファイル形式は十分に文書化されており、elf 固有のディレクティブ (存在する場合) が何を行っているかを実際に確認したい場合は、非常に簡単に解析できます。これらのディレクティブの多くは、何よりもリンカーを支援するためのものです。.thumb_func、.text、.data など。

于 2010-12-14T23:44:28.367 に答える
7

プログラムのセクションは、ほとんどのシステム (Linux、BSD など) がオブジェクトと実行可能ファイルを格納する ELF 形式と密接に関連しています。この記事は、ELF がどのように機能するかについての優れた洞察を提供し、セクションの理由を理解するのに役立ちます。

簡単に言えば、セクションを使用すると、アドレス、実行および書き込みの許可など、さまざまなプロパティを持つさまざまなメモリ領域にプログラムを編成できます。最終的なリンク段階で、リンカーは通常、同じセクションのすべてのセクションをグループ化する特定のリンカー スクリプトを使用します。まとめて名前を付け (たとえば、すべてのコンパイル単位のすべてのコードをまとめて ...)、それらにメモリ内の最終アドレスを割り当てます。

組み込みシステムの場合、それらの使用は特に明白です。まず、ブート コード (通常は.textセクションに含まれる) を実行するには、固定アドレスにロードする必要があります。次に、読み取り専用データを専用の読み取り専用セクションにグループ化し、デバイスの ROM 領域にマップすることができます。最後の例: オペレーティング システムには、一度だけ呼び出され、その後は使用されない初期化関数があり、貴重なメモリ スペースが浪費されます。これらすべての初期化関数が、次のように呼ばれる専用セクションにグループ化されている場合、.initcode、およびこのセクションがプログラムの最後のセクションに設定されている場合、オペレーティングシステムは、独自のメモリの上限を下げることにより、初期化が完了すると、このメモリを簡単に再利用できます。たとえば、Linux はそのトリックを使用することが知られており、GCC を使用すると、変数またはメソッドを特定のセクションに配置することができます。__attribute__ ((section ("MYSECTION")))

.type実際に.sizeは私にもまだかなり不明です。私はそれらをリンカーのヘルパーと見なしており、アセンブラーによって生成されたコード以外では見たことがありません。

.thumb_funcArmコードとの相互作用を可能にするために、古いOABIインターフェースにのみ必要なようです。古いツールチェーンを使用していない限り、おそらく心配する必要はありません。

于 2010-12-14T07:06:10.303 に答える
6

最近の binutils (2.21.53 (MacPorts) と 2.22 (Yagarto 4.7.1) で検証済み) で ARM と Thumb のインターワーキングが壊れた理由を突き止めようとしたときに、これに遭遇しました。

私の経験から、.thumb_func以前の binutils で問題なく動作し、正しいインターワーキング ベニアが生成されました。ただし、最近のリリースでは、 .type *name*, %function適切なベニア生成を確実にするためにディレクティブが必要です。

binutils メーリング リストへの投稿

古いバージョンの binutils を掘り下げて、.typeディレクティブが.thumb_func以前の binutils の代わりに十分かどうかを確認するのが面倒です。コードに両方のディレクティブを含めても害はないと思います。

編集:コードでの使用に関するコメントを更新し.thumb_funcました。明らかに、ARM->Thumb インターワーキングが Thumb ルーチンにフラグを立ててベニアを生成するように動作しますが、.typeディレクティブが ARM 関数にフラグを立てるために使用されない限り、Thumb->ARM インターワーキングは失敗します。

于 2012-09-05T03:52:16.817 に答える