1

addコマンドが使用されているARMアセンブリのスニペットに焦点を当てています。以下のスニペットは、単純に次のように述べています。 プログラム カウンタのアドレスに、 に格納されている文字列の位置を見つけるために計算されたオフセットを追加しL._strますL._str

movw    r0, :lower16:(L_.str-(LPC1_0+4))
movt    r0, :upper16:(L_.str-(LPC1_0+4))
LPC1_0:
    add r0, pc

最初の 2 つの命令 (movwおよびmovt) は、その文字列のアドレスを表す 32 ビットの数値をロードします。私は親指モードですよね?わかりました、そう言ったので、全体的なメモリ レイアウトを把握する方法がわかりません。以下は、メモリのコード セグメントの正しい表現ですか? またLPC1_0L._strベースアドレスは文字列add r0, pcのアドレスですか?A simple string各箱の寸法は?アーキテクチャに応じて 32 ビットまたは 64 ビット。

--------------------------------------------
| movw    r0, :lower16:(L_.str-(LPC1_0+4)) |
--------------------------------------------
| movt    r0, :upper16:(L_.str-(LPC1_0+4)) |
-------------------------------------------- LPC1_0
| add r0, pc                               |
--------------------------------------------
                       .
                       .
                       .
-------------------------------------------- L._str
| "A simple string"                        |
--------------------------------------------

pcもしそうなら、差分を使用してオフセット (に追加される) を取得できますL_.str-LPC1_0。しかし、ここ+4でも考慮されます。

ADD、PC または SP 相対から

ADD Rd、Rp、#expr

Rp が pc の場合、使用される値は (現在の命令のアドレス + 4) AND &FFFFFFFC です。

そのため、オフセット オフセットのバイト数も考慮する必要があるようpcです。Ok。それで、これらのバイトはどこに追加されますか?これらの 4 バイトが、コマンドの前ではなく、命令で考慮されるのはなぜですか? これはコンパイラによって導入された最適化機能ですか?Rp+4movadd

4

2 に答える 2

1

通常の位置に依存しない「何かのアドレスを取得する」命令は単純ですadr, r0, L._str(これは、アセンブラ/リンカに の適切なオフセットを自動的に計算させることと同じですadd r0, pc, #offset)。ただし、ARM アーキテクチャは固定幅エンコーディングを使用するため (ARM 命令は 32 ビット幅で、Thumb 命令は 16 ビットまたは 32 ビットです)、オフセットの即値をエンコードするために使用できる命令のビット数は限られているため、最大範囲は制限されています。Thumb エンコーディングadrがサポートできる最大オフセットは、+/-4095 バイトです。コンパイラーは、リンカーがセクションをどれだけ離して配置するかを認識していないため、安全に出力できません。adr最終オフセットが大きすぎてアセンブルできないリスクがあるため、代わりに 3 命令生成即時/追加 PC シーケンスを取得します。利点は、任意の 32 ビット アドレスに到達できることです。トレードオフは、プログラム イメージと命令キャッシュでより多くのスペースを占有することです。adr単独で 2 バイトまたは 4 バイト (オフセットとターゲット レジスタによって異なります) 、movw//シーケンス重さは 10 バイトで、実行には少なくとも 2 倍の時間がかかります。movtadd

PC オフセットがセクション オフセットに組み込まれている理由については、そうではないのはなぜですか? 両方とも一定であるため、リンカが/命令に即値をエンコードするために最終イメージ内のLPC1_0との間の距離を計算する場合、PC 補正を同時に追加しないことによって得られるものはまったくありません。これが、元の ARM の 3 ステージ パイプラインの 2 命令フェッチ/実行オフセットが最初に公開された理由です。ソフトウェアをビルドするときに、すべてのロジックを実装するよりも、アセンブラ/リンカでアドレスを修正する方がかなり簡単だったからです。ハードウェアで「修正」します。L_.strmovwmovt

于 2015-02-23T19:50:49.607 に答える
1

私の経験に基づいた推測:

メモリ内の「絶対」アドレスを取得したいL_.str。 即値を追加するように見えるため、値はオペコード内にありますmovwmovt

コンパイラはLPC1_0との間のオフセットを計算し、L_.str別の4(バイト) を減算します。

指示はその価値にadd r0,pc 追加pc+4されます。

+4 はプロセッサによって追加されます。これは、プロセッサの「ロジック」で pc がかなり早い段階でインクリメントされ、追加でのみ pc の値を読み取ることができるためだと思います。プロセッサpc+4が追加するロジックを追加するよりも、実際にそうであることを文書化する方が簡単です...pc+4-4

アドレスを計算するソリューション全体の利点は、L_.strそのコードの再配置とは無関係であることです。

于 2015-02-23T10:31:23.573 に答える