ARMアセンブリ言語を勉強し始めたところです。MOVを使用して即値をレジスターに転送する方法についてはわかりません。
ARMリファレンスマニュアルと私の教科書から、MOV命令の直後の数値の範囲は0〜255であると言われています。しかし、ADS 1.2 IDEで自分のPCでテストすると、命令
MOV R2, #0xFFFFFFFF
うまくいきます。仕様によると、0xFFFFFFFFは範囲外ではありませんか?
誰かが私に手を貸してくれることを願っています。
よろしく。
ARMは、ARMのオペコードに組み込まれているバレルシフタの一部として、即値に対して特定の一連の操作を実行できることに注意してください。
この小さな記事には、ARMアセンブラーがARM命令の使用可能な小さなスペースに大きな即値を合わせるために使用できるいくつかのトリックの最も明確な説明の1つがあります。
この記事では、MVNオペコードを生成して即値のビット単位の補数をロードする特定の例で使用される可能性が高いトリックについて説明します。
これらの種類の操作はすべての即値で実行できるわけではありませんが、ARMアセンブラはおそらくかなり賢いです(そしてCコンパイラは確かにそうです)。シフト/補数トリックが実行できない場合、値は通常、PC相対の場所から読み込まれるか、複数の命令から値を「構築」することによって読み込まれます。
1つのARM命令は、任意のeven 2の累乗でシフトされた8ビットの即値として表すことができる即値定数のみをエンコードできます。
ただし、MVN
命令もあり、これはMOV
に似ていますが、すべてのビットを反転します。したがって、MOV R2, #0xFFFFFFFF
はMOV
命令としてエンコードできませんが、MVN R2, #0
としてエンコードできます。アセンブラーがこの変換を実行する場合があります。
与えられた定数が有効範囲内にあるかどうかを判断するのは少し難しいです。
すでに述べたマシューのように、アセンブラは、与えられた命令を、mov/mvn、cmp/cmn、tst/tneなどの類似した否定の命令に置き換えることによって、あなたに手を貸します。
MOV命令は、imm16値またはOperator2値(メモリアラインメントではなく命令長のため)を受け入れることができます。これらは、次の規則のいずれかに準拠する必要があります(CortexM命令セットマニュアルからコピー、XおよびYは任意の16進値):
これが0xFFFFFFFFが受け入れられる理由です(4番目の規則に準拠)。
独自の32ビット定数をアセンブルしたい場合は、レジスタの上半分に書き込む命令[〜#〜] movt [〜#〜]を使用できます。
元の値の符号拡張からアーティファクトが見られる場合があります。逆アセンブリの表示に使用しているツールが0..255を符号付きバイトとして処理する場合、それをより大きいint型(またはレジスター)にロードすると、すべての上位ビットが元の符号ビットで埋められます値。言い換えると、0xFFが符号付きバイトの場合、10進数の値は-1です。これを32ビットレジスタに入力すると、16進数は0xFFFFFFFFのようになり、10進数の値は-1のままです。
0x7Fなど、上位ビットが設定されていない値を使用してみてください。符号ビットが設定されていないため、より大きなint型のレジスタまたはフィールドにロードされると、上位ビットがゼロで埋められると思います。
コンパイラー/アセンブラーがユーザーが指定した値を切り捨てることも可能です。私はそれをソースコードエラーと見なしますが、アセンブラーは面白い獣です。 0x7FFを指定した場合、0x7FF(切り捨てられておらず、0..255より大きい)または0xFFFFFFFF(0..255に切り捨てられた、符号付きバイト)にコンパイルされますか?
0xffffffffをレジスタに移動したい場合は、いつでも実行できます。
MOV R0, #-1
0xffffffffは-1の2の補数表現であるため