1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ラズパイでARM入門(7.インデクシングモード)

Last updated at Posted at 2021-03-01

前回:6. 制御構造 - if文 while文 次回:8.配列と構造体、その他のインデクシングモード
目次(記事一覧)

※この記事はRoger Ferrer IbáñezさんのブログARM assembler in Raspberry Pi – Chapter 7の翻訳です。

ARMアーキテクチャは、長年組み込みシステムを対象としてきました。組み込みシステムは通常、大量生産される製品(食器洗い機、携帯電話、テレビなど)に使用されますが、売価と原価の差が非常に小さいため、設計者は可能な限り構成部品を節約しようとします(数十万、あるいは数百万の製品から1セントを節約するだけでも利益があるかもしれません)。メモリは日々価格が下がってきているとはいえ、部品の中でも比較的高価な部類に入ります。とにかく、メモリに制約がある環境ではメモリを節約できるに越したことはありません。ARMの命令セットはそのようなことを念頭において設計されています。これらのテクニックをすべて学ぶためにはあと何章か必要です。今回は「オペランドのシフト」と呼ばれる機能から始めます。

インデクシングモード

これまでにわかったことは、ARM命令は、ロード(ldr)、ストア(str)、分岐(b または bXX)を除き、オペランドとしてレジスタか即値のいずれかを取る、ということです。また、最初のオペランドは通常、デスティネーション(destination 目的値)レジスタであることもわかりました。ただしstrは例外で、目的値がメモリのため最初のオペランドはソースの役割です。mov命令は目的値に加えもう一つレジスタか即値のオペランドを取ります。addandなど算術命令は目的値に加えもう2つのソースレジスタを取り、1つ目は必ずレジスタで、2つ目はレジスタか即値です。

命令において許可されるこのようなオペランドの組は、まとめてインデクシングモードと呼ばれます。今日では、この概念は何もインデックス(索引付け)しないため少し見当違いな名前です。インデクシングという名前はメモリオペランドでは意味を持ちますが、ARM命令はロードとストアを除いてメモリオペランドを取りません。とはいえARMのドキュメントにある用語であるためその呼び方をするのが懸命でしょう。

ほとんどのARM命令の構文は次のパターンでまとめられます。

instruction Rdest, Rsource1, source2

これには例外があり、主にムーブ(mov)、分岐、ロード、ストアが該当します。実際のところムーブ命令はそこまで違いはありません。

mov Rdest, source2

RdestRsource1は必ずレジスタです。次節でsource2について述べます。

ロード命令とストア命令のインデクシングモードについては今後の記事で議論します。一方、分岐命令は驚くほど単純で、唯一のオペランドがプログラム中のラベルのためインデクシングモードについて説明することはほとんどありません。

オペランドのシフト

上記の命令パターンにおけるこの不思議なsource2は何でしょうか?前章では、レジスタか即値を使いました。つまり、少なくともsource2はレジスタか即値です。source2の部分にはレジスタか即値が使用できます。以下に前章でも使われた例を示します。

mov r0, #1
mov r1, r0
add r2, r1, r0
add r2, r3, #4

しかし、source2は単なるレジスタや即値以上のものになり得ます。実際、レジスタの場合はシフト演算と組み合わせることができます。すでにこれらのシフト演算の1つは第6章で見ました。全てではありませんがこのようなものがあります。

構文 由来 意味 解説
LSL #n Logical Shift Left 論理左シフト ビットをn回左にシフトする。左端からn個のビットは失われ、右端からn個のビットに0がセットされる。
LSL Rsource3 - - 上と同様だが、レジスタの下位バイトがシフト量を決める。
LSR #n Logical Shift Right 論理右シフト ビットをn回右にシフトする。右端からn個のビットは失われ、左端からn個のビットに0がセットされる。
LSR Rsource3 - - 上と同様だが、レジスタの下位バイトがシフト量を決める。
ASR #n Arithmetic Shift Right 算術右シフト LSRと同様だが左端からn個のビットにセットするのは0ではなく、シフト前の左端のビットとなる。
ASR Rsource3 - - 上と同様だが、レジスタの下位バイトがシフト量を決める。
ROR #n Rotate Right 右ローテート LSRと同様だが、右端からn個のビットは失われず、左端からn個のビットにセットされる。
ROR Rsource3 - - 上と同様だが、即値の代わりにレジスタの下位バイトを使用する。

上の表におけるnは1から31までの即値です。これらの追加の演算は、2番目のソースレジスタの値(レジスタそのものではない)に適用できるため、1つの命令で複数の操作を行えることになります。ARMには直接シフトする命令はありません。mov命令を使います。

mov r1, r2, LSL #1

なぜレジスタの値を左または右にシフトしたいのかと疑問に思うかもしれません。第6章では値を左にシフト(LSL)することで2を掛けるのと同じ値が得られることがわかりました。逆に、2の補数表現(符号あり整数)ならASRで、その他の場合はLSRで右にシフトをすると2で割ることができます。シフトは結果的に値を$2^n$で乗算または除算しています。

mov r1, r2, LSL #1      /* r1 ← (r2*2) */
mov r1, r2, LSL #2      /* r1 ← (r2*4) */
mov r1, r3, ASR #3      /* r1 ← (r3/8) */
mov r3, #4
mov r1, r2, LSL r3      /* r1 ← (r2*16) */

addと組み合わせてこんなこともできます。

add r1, r2, r2, LSL #1   /* r1 ← r2 + (r2*2) つまり r1 ← r2*3 */
add r1, r2, r2, LSL #2   /* r1 ← r2 + (r2*4) つまり r1 ← r2*5 */ 

subでも似たことができます。

sub r1, r2, r2, LSL #3  /* r1 ← r2 - (r2*8) つまり r1 ← r2*(-7) */

ARMには便利なrsbReverse Substract)命令があります。subRdest ← Rsource1 - source2を計算するのに対してrsbRdest ← source2 - Rsource1を計算します。

rsb r1, r2, r2, LSL #3      /* r1 ← (r2*8) - r2 つまり r1 ← r2*7 */

次の例は少々凝っています。

/* r1の初期値に42を掛ける = 7*3*2 */
rsb r1, r1, r1, LSL #3  /* r1 ← (r1*8) - r1 つまり r1 ← 7*r1 */
add r1, r1, r1, LSL #1  /* r1 ← r1 + (2*r1) つまり r1 ← 3*r1 */
add r1, r1, r1          /* r1 ← r1 + r1     つまり r1 ← 2*r1 */

なぜシフトを使用して乗算をしようとするのか疑問かもしれません。一般的な乗算命令はもちろんありますが、ARMプロセッサーによる計算はシフト演算よりはるかに重く時間ががかかることもあります。それを使うしか選択肢がないこともありますが、たいてい使用される小さな定数値の場合、単一の命令のほうが効率的です。

ローテーションは日常の使用においてシフトよりも有用ではありません。ローテーションは通常、暗号化においてビット列を並び替えて「スクランブル」するために使用されます。ARMは左にローテートする命令を用意していませんが、左にn回転することは右に32-n回転することで実現できます。

/* r1の初期値が0x12345678だったとする */
mov r1, r1, ROR #1   /* r1 ← r1 ror 1. これは r1 ← 0x91a2b3c */
mov r1, r1, ROR #31  /* r1 ← r1 ror 31. これは r1 ← 0x12345678 */

今日はここまで。

次回:8.配列と構造体、その他のインデクシングモード

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?