ロード命令 (1) ()

これから ARM64 の個々の命令の解説を順次進めていきますが、 まず最初に命令の中で種類が最も多く、複雑なロード命令を 説明することにします。 このロード命令を攻略すると ARM64 の他の命令 (ストア命令も) の複雑さは大したことありません。

ロード命令(LDR)はメモリに格納されている値をレジスタに読み込み、 ストア命令はレジスタに入っている値をメモリに書き出す命令です。 コンピュータは、ほとんどすべての作業をメモリを介して行うので、 ロード/ストア命令はよく使われます。

レジスタ-メモリ転送 読み 命令
メモリからレジスタへコピー ロード LDR
レジスタからメモリへコピー ストア STR
レジスタからレジスタへコピー ムーブ MOV

アドレッシング

プログラム自身もデータもファイルから読み出されて、メモリに格納されてから処理を行います。 したがって、メモリに対して読み書きするロード/ストア命令は大変重要です。 ロード/ストア命令では読み書きするメモリの位置(メモリアドレス)を 指定する必要がありますが、この位置の指定方法を「アドレッシング」 と呼びます。CPUの種類(x86, x64, ARM, Arm64、PowerPC など)によって、 「アドレッシング」の方法が異なるため、新しい CPU のアセンブリ言語を 習得しようとする場合、「アドレッシング」の方法を早く理解することがコツです。

ARM64のロード/ストア命令のアドレッシングには、大きく分けて イミディエートオフセット、レジスターオフセット、 リテラル(プログラムカウンタ相対オフセット) の3種類があります。 今回は使用頻度が高くて複雑なイミディエートオフセットレジスターオフセット の2種類を紹介します。

addressing

上の図は、ARM64でメモリの位置を指定する方法を示しています。 ベースレジスタとして働く汎用レジスタまたはスタックポインタの示す メモリの番地を基本として、オフセットと呼ばれる数値を加減算した アドレスのデータを読み書きします。 図の中の「オフセット」が 定数のものがイミディエートオフセット、このオフセットもレジスタに 格納された値を使うものがレジスターオフセットです。

イミディエートオフセット

レジスタ (Xn または SP) が格納している値をメモリアドレスとして、 その値に定数を加えてメモリアドレスとするアドレッシングを イミディエートオフセット (immediate offset) といいます。 ARM64では、64ビットレジスタにメモリ中のアドレスを格納して、 そのメモリアドレスに対してデータを読み書きします。 レジスタが格納しているメモリアドレスに対して、比較的小さい 整数値、例えば +16 とか -200 といった定数値を加えたアドレスに アクセスしたい場合があります。 そのような場合のために命令自体に比較的小さい整数値を 埋め込むことができます。 この値をイミディエートと呼び、日本語では即値と訳されます。

符号付き 9 ビットオフセット

ロード命令では、 9ビットの符号付き定数(+255..-256)を使う アドレッシングとして、プレインデックスとポストインデックス があります。これらの 2 種類はベースレジスタにオフセットを 加えてベースレジスタを更新します。 また、LDUR 系の命令として ベースレジスタへの変更を行わない符号付き 9 ビットオフセット のアドレッシングがあります。

プレインデックス

プレインデックスは、ベースレジスタと呼ぶスタックポインタ (SP) または 64 ビット汎用レジスタ (Xn) が格納している アドレスに定数を加えたメモリアドレスから読み出し、 そのアドレスをベースレジスタに書き戻します。 結果として、ベースレジスタの値に定数を加えたメモリアドレス を使ってベースレジスタを「事前に」更新し、そこにアクセス していることになります。ベースレジスタを「事前に」更新する ことから「プレインデックス」と呼んでいます。 次の擬似コードでは、memory[ adr ] でメモリアドレス adr に 格納されている内容を示します。 base はベースレジスタ(Xn または SP)、Xt は転送先のレジスタを 示します。 プレインデックスはオペランドの最後に「!」を付けて表します。

  LDR   Xt, [base,  #simm9]!     // プレインデックス

    // プレインデックス
    base = base + simm9;
    Xt = memory[base];
ポストインデックス

ポストインデックスはベースレジスタの示すメモリアドレスから 読みだした後、オフセットに指定した定数をベースレジスタに加算します。 つまり、ベースレジスタのメモリアドレスにアクセスした「後に」 ベースレジスタを別のメモリアドレスに更新することから 「ポストインデックス」と呼んでいます。

  LDR   Xt, [base], #simm9       // ポストインデックス

    // ポストインデックス
    Xt = memory[base];
    base = base + simm9;
Unscaled

9ビットの符号付き定数を使うアドレッシングモードにはもう一つあって、 LDUR 命令は、ポストインデックスでもプレインデックスでもない 動作をします。ベースレジスタにオフセットを加えたメモリから ロードするのは同じですが、ベースレジスタ base の値を更新しません。

  LDUR  Xt, [base, #simm9]       // base への書き戻しなし

    Xt = memory[base + simm9];

この LDUR 命令も「LDR」というニーモニック(命令の名前)のほうが 適していると思いますが、ARM (会社の方) は次に説明する符号無し 12 ビットオフセットアドレッシングの方に「LDR」というニーモニックを 割り当てることにしたようです。「U」は Unscaled の略で、 次の符号無し12ビットオフセットと異なって、 オフセットに対して転送するバイト数を乗算するスケーリングを 行わないことを意味しています。 いつも LDR というニーモニックを 使っていれば、必要な場合に LDUR 命令と LDR 命令の符号無し 12 ビット オフセットをアセンブラが自動的に選択して使ってくれるので、 通常はこのアドレッシングモードを意識する必要はありません。 転送バイト数の倍数になっていないオフセット値で、かつオフセットが +255 .. -256 を超える場合に、アセンブラはエラーを出力します。

符号無し12ビットオフセット

ベースレジスタに格納されている値に符号無し 12 ビットの即値 (0 .. 4095) を加えた値のメモリアドレスに格納されているメモリの内容を レジスタにコピーします。

  LDR  Xt, [base, #uimm12]           // base に書き戻さない

    Xt = [base + uimm12 * scale];  // scale = 1,2,4,8

12ビットの定数は転送するバイト数にしたがって 1、2、4、8 倍に スケーリングされます。したがって実際のオフセットは 1 バイトの ロードでは (0 .. 4095)、ハーフワードでは (0 .. 8190)、ワード (32ビット) では (0 .. 16380)、ダブルワード (64ビット) では (0 .. 32760) の範囲のオフセットを使用することができます。 C 言語の配列で考えると 4096 個の要素に定数インデックスで アクセスできることになります。 符号付き 9 ビットオフセットと異なって負のオフセットは使えず、 転送するバイト数を倍数とするオフセット値に限定されます。

レジスタオフセット

ベースレジスタ (Xn または SP) が保持しているメモリアドレスに、 インデックス用のレジスタが格納しているオフセット値を加えた メモリアドレスの内容を転送先レジスタ(Xt)にコピーします。 インデックス用レジスタ (Rm) には 32ビットレジスタ (Wm) または 64ビットレジスタを指定できます。 オフセット値は 32ビットレジスタならば4倍、 64ビットレジスタの場合は8倍するように指定することもできます。 32ビットレジスタの場合でも符号拡張を指定することが可能なため、 負のオフセット値を使うことができます。

64ビットのロードを例にすると、次のような命令の形式となります。

  LDR   Xt, [base, Wm {, SXTW|UXTW {#0|#3}} ] 
  LDR   Xt, [base, Xm {, LSL|SXTX {#0|#3}} ] 

    Xt = memory[base + Rm {* 8} ]

32ビットのロードの場合は、次のようにシフト量が #2 (4倍) を指定できます。

  LDR   Wt, [base, Wm {, SXTW|UXTW {#0|#2}} ] 
  LDR   Wt, [base, Xm {, LSL|SXTX {#0|#2}} ] 

    Wt = memory[base + Rm {* 4} ]

命令中の SXTW | UXTW または LSL | SXTX は拡張(extend)指定子で、 インデックス用レジスタの値を 32ビットから 64ビットに拡張する 場合に符号拡張を行う(SXTW)かどうかを指定します。 64ビットの場合に LSL を指定すると転送バイト数倍のシフトを指定できます。 シフト量は省略可能で LSL でない場合は #0 になります。 シフト量は任意のビット数が指定できるわけでは無く、 「シフトするか/しないか」の2択です。アセンブラのオペランドの記述には 転送バイト数に応じたシフトするビット数を指定する必要があります。

ロード命令の概要

ロード命令には、データのメモリー中でのサイズと転送先のレジスタの サイズが異なる命令が次のように 9種類あります。読み込むデータが 1 バイト (8ビット)から 8 バイト (64ビット)にもかかわらず、転送先のレジスタが 32ビットと64ビットの2種類の指定しかできないために命令が多くなっています。

メモリのデータサイズとレジスタのサイズの組み合わせによっては 命令が存在しない組み合わせがあります。ここでは区別しやすいように、 存在する 9 種類をデータサイズの大きいものから順に番号を付けています。

メモリ 符号 転送先(32) 転送先(64)
ビット数 Wt Xt
64ビット無符号- LDR [1]
符号付
32ビット無符号 LDR [2]
符号付 LDRSW [3]
16ビット無符号 LDRH [4] -
符号付 LDRSH [5] LDRSH [6]
8ビット無符号 LDRB [7] -
符号付 LDRSB [8] LDRSB [9]

小さいビット幅のデータをビット幅が大きいレジスタに転送する場合には、 データのビット幅を広げる必要があります。この時にレジスタの上位ビットに 0 を設定(ゼロ拡張)するか、データを符号付きの整数と考えてデータの最上位ビットを レジスタの上位ビットにコピー(符号拡張)するかで2種類の拡張方法があります。 上の表で符号無しの場合はゼロ拡張、符号付きの場合は符号拡張になります。

ロード命令の詳細

メモリのデータサイズとレジスタのサイズの組み合わせ毎にデータサイズの 大きいものから順に紹介します。 9 種類の命令はそれぞれ6種類の同じ アドレッシングを使うことができます。

6種類のアドレッシングは、次のものです。


[1] LDR ダブルワード(64ビット) → 64ビット

ARM64 にとって、一番自然なサイズである64ビットのデータをメモリから 読み取って、64 ビットレジスタに格納する命令です。 データとレジスタのビット幅が等しいため、符号の有無で命令のバリエーション はありません。

  LDR   Xt, [base], #simm9       // ポストインデックス
  LDR   Xt, [base,  #simm9]!     // プレインデックス
  LDUR  Xt, [base,  #simm9]
  LDR   Xt, [base {,#uimm12} ]   // 符号なしオフセット(8の倍数) [0 - 32760] 
  LDR   Xt, [base, Wm {,SXTW|UXTW {#0 | #3}} ]  // レジスタオフセット
  LDR   Xt, [base, Xm {,LSL|SXTX {#0 | #3}} ]  // レジスタオフセット

オフセットの値によって、9ビットの符号付オフセットのLDUR命令と、 12ビットの符号なしオフセットのLDR命令のどちらを使うかはアセンブラが 自動的に決めてくれます。LDUR命令を使う必要はなく、常にLDR命令を 使えば大丈夫です。 下のリストは即値オフセットのロード命令と GNU as の翻訳結果のビットパターンです。 必要な場合は LDR 命令が LDUR 命令に変換されているのが分かります。

        // 正整数で8の倍数
        ldr    x0, [x9, #8]
            |---+---|---+---|---+---|---+--0
            11111001010000000000010100100000   --> LDR

        // LDURを指定
        ldur   x0, [x9, #8]
            |---+---|---+---|---+---|---+--0
            11111000010000001000000100100000   --> LDUR

        // 8の倍数でない
        ldr    x0, [x9, #9]
            |---+---|---+---|---+---|---+--0
            11111000010000001001000100100000   --> LDUR

        // 正の整数でない
        ldr    x0, [x9, #-8]
            |---+---|---+---|---+---|---+--0
            11111000010111111000000100100000   --> LDUR

        // オフセットの範囲が9ビットを超える
        ldr    x0, [x9, #512]
            |---+---|---+---|---+---|---+--0
            11111001010000000000010100100000   --> LDR

        // LDUR のオフセットの範囲を超える
        ldur   x0, [x9, #512] --> エラー

他のLDUR系の命令(LDURSW、LDURH、LDURSH、LDURB、LDURSB)も 同じように、必要な場合はアセンブラにより LDUR 命令に変換されます。

命令のエンコード

表中で simm9 は9ビットの符号付イミディエート値(-256 .. +255)、 uimm12 は符号なし12ビットイミディエート値(0 .. 4095) を示します。 Rn はベースアドレスを格納する汎用レジスタ(X0..X31)または スタックポインタ(SP)、Rt はデータの転送先となるレジスタです。

アクセスするメモリのデータサイズは命令先頭の 2bit が表しています。

LDR 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 1 1 1 1 1 0 0 0 0 1 0 simm9 0 1 Rn Rt
pre index 1 1 1 1 1 0 0 0 0 1 0 simm9 1 1 Rn Rt
LDUR 1 1 1 1 1 0 0 0 0 1 0 simm9 0 0 Rn Rt
unsigned 12 1 1 1 1 1 0 0 1 0 1 uimm12 Rn Rt
register 1 1 1 1 1 0 0 0 0 1 1 Rm option S 1 0 Rn Rt


[2] LDR ワード(32ビット) → 32ビット

メモリから 32 ビットのデータを読み取って、32 ビットレジスタに 格納する命令です。32ビットレジスタは W0 から W30 までありますが、 64ビットレジスタの下位 32 ビットに格納されます。上位32ビットは 0 に 設定されます。 データと転送先レジスタのビット幅が等しいため、 符号の有無で命令のバリエーションはありません。

  LDR   Wt, [base], #simm9     // ポストインデックス
  LDR   Wt, [base,  #simm9]!   // プレインデックス
  LDUR  Wt, [base,  #simm9]
  LDR   Wt, [base {,#uimm12} ]  // 符号なしオフセット(4の倍数) [0 - 16380] 
  LDR   Wt, [base, Wm {,SXTW|UXTW {#0 | #2}} ] 
  LDR   Wt, [base, Xm {,LSL|SXTX {#0 | #2}} ] 

命令のエンコード
LDR 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 1 0 1 1 1 0 0 0 0 1 0 simm9 0 1 Rn Rt
pre index 1 0 1 1 1 0 0 0 0 1 0 simm9 1 1 Rn Rt
LDUR 1 0 1 1 1 0 0 0 0 1 0 simm9 0 0 Rn Rt
unsigned 12 1 0 1 1 1 0 0 1 0 1 uimm12 Rn Rt
register 1 0 1 1 1 0 0 0 0 1 1 Rm option S 1 0 Rn Rt


[3] LDRSW 符号付きワード(32ビット) → 64ビット

メモリから 32 ビットのデータを読み取って、64 ビットレジスタに 符号拡張して格納する命令です。 32ビットのデータが 負(最上位ビットが「1」)の場合には、64ビットレジスタの 上位32ビットをすべて「1」とします。32ビットで負の値は 64ビットでも同じ負の値となります。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDR、LDRSW)があります。

  LDRSW  Xt, [base], #simm9     // ポストインデックス
  LDRSW  Xt, [base,  #simm9]!    // プレインデックス
  LDURSW Xt, [base,  #simm9]
  LDRSW  Xt, [base {,#uimm12} ]  // 符号なしオフセット(4の倍数) [0 - 16380]
  LDRSW  Xt, [base, Wm {,SXTW|UXTW {#0 | #2}} ]
  LDRSW  Xt, [base, Xm {,LSL|SXTX {#0 | #2}} ]

命令のエンコード
LDRSW 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 1 0 1 1 1 0 0 0 1 0 0 simm9 0 1 Rn Rt
pre index 1 0 1 1 1 0 0 0 1 0 0 simm9 1 1 Rn Rt
LDURSW 1 0 1 1 1 0 0 0 1 0 0 simm9 0 0 Rn Rt
unsigned 12 1 0 1 1 1 0 0 1 1 0 uimm12 Rn Rt
register 1 0 1 1 1 0 0 0 1 0 1 Rm option S 1 0 Rn Rt


[4] LDRH ハーフワード(16ビット) → 32ビット

メモリから 16 ビットのデータを読み取って、32 ビットレジスタに ゼロ拡張して格納する命令です。 32ビットレジスタの 上位16ビットをすべて「0」とします。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDRH、LDRSH)があります。

  LDRH  Wt, [base], #simm9      // ポストインデックス
  LDRH  Wt, [base,  #simm9]!     // プレインデックス
  LDURH Wt, [base,  #simm9]
  LDRH  Wt, [base {,#uimm12} ]   // 符号なしオフセット(2の倍数) [0 - 8190]
  LDRH  Wt, [base, Wm {,SXTW|UXTW {#0 | #1}} ]
  LDRH  Wt, [base, Xm {,LSL|SXTX  {#0 | #1}} ]

命令のエンコード
LDRH 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 0 1 1 1 1 0 0 0 0 1 0 simm9 0 1 Rn Rt
pre index 0 1 1 1 1 0 0 0 0 1 0 simm9 1 1 Rn Rt
LDURH 0 1 1 1 1 0 0 0 0 1 0 simm9 0 0 Rn Rt
unsigned 12 0 1 1 1 1 0 0 1 0 1 uimm12 Rn Rt
register 0 1 1 1 1 0 0 0 0 1 1 Rm option S 1 0 Rn Rt


[5] LDRSH 符号付きハーフワード(16ビット) → 32ビット

メモリから 16 ビットのデータを読み取って、32 ビットレジスタに 符号拡張して格納する命令です。 16ビットのデータが 負(最上位ビットが「1」)の場合には、32ビットレジスタの 上位16ビットをすべて「1」とします。16ビットで負の値は 32ビットでも同じ負の値となります。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDRH、LDRSH)があります。

  LDRSH  Wt, [base], #simm9     // ポストインデックス
  LDRSH  Wt, [base,  #simm9]!   // プレインデックス
  LDURSH Wt, [base,  #simm9]
  LDRSH  Wt, [base {,#uimm12} ]  // 符号なしオフセット(2の倍数) [0 - 8190]
  LDRSH  Wt, [base, Wm {,SXTW|UXTW {#0 | #1}} ] 
  LDRSH  Wt, [base, Xm {,LSL|SXTX  {#0 | #1}} ] 

命令のエンコード
LDRSH 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 0 1 1 1 1 0 0 0 1 1 0 simm9 0 1 Rn Rt
pre index 0 1 1 1 1 0 0 0 1 1 0 simm9 1 1 Rn Rt
LDURSH 0 1 1 1 1 0 0 0 1 1 0 simm9 0 0 Rn Rt
unsigned 12 0 1 1 1 1 0 0 1 1 1 uimm12 Rn Rt
register 0 1 1 1 1 0 0 0 1 1 1 Rm option S 1 0 Rn Rt


[6] LDRSH 符号付きハーフワード(16ビット) → 64ビット

メモリから 16 ビットのデータを読み取って、64 ビットレジスタに 符号拡張して格納する命令です。 16ビットのデータが 負(最上位ビットが「1」)の場合には、64ビットレジスタの 上位48ビットをすべて「1」とします。16ビットで負の値は 64ビットでも同じ負の値となります。 データより転送先レジスタが大きいため、符号の有無で2つの命令が 必要となりますが、16ビットから64ビットへの符号なし拡張(ゼロ拡張)はLDRH [4]と 同じ動作になるため、専用の命令はありません。

  LDRSH  Xt, [base], #simm9     // ポストインデックス
  LDRSH  Xt, [base,  #simm9]!   // プレインデックス
  LDURSH Xt, [base,  #simm9]
  LDRSH  Xt, [base {,#uimm12} ]  // 符号なしオフセット(2の倍数) [0 - 8190]
  LDRSH  Xt, [base, Wm {,SXTW|UXTW {#0 | #1}} ] 
  LDRSH  Xt, [base, Xm {,LSL|SXTX {#0 | #1}} ] 

命令のエンコード
LDRSH 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 0 1 1 1 1 0 0 0 1 0 0 simm9 0 1 Rn Rt
pre index 0 1 1 1 1 0 0 0 1 0 0 simm9 1 1 Rn Rt
LDURSH 0 1 1 1 1 0 0 0 1 0 0 simm9 0 0 Rn Rt
unsigned 12 0 1 1 1 1 0 0 1 1 0 uimm12 Rn Rt
register 0 1 1 1 1 0 0 0 1 0 1 Rm option S 1 0 Rn Rt


[7] LDRB バイト(8ビット) → 32ビット

メモリから 8 ビットのデータを読み取って、32 ビットレジスタに ゼロ拡張して格納する命令です。 32ビットレジスタの 上位24ビットをすべて「0」とします。 メモリ上のデータを1バイトずつ読み取るので、比較的使う機会が多い命令です。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDRB、LDRSB)があります。

  LDRB  Wt, [base], #simm9     // ポストインデックス
  LDRB  Wt, [base,  #simm9]!    // プレインデックス
  LDURB Wt, [base,  #simm9]
  LDRB  Wt, [base {,#uimm12} ]  // 符号なしオフセット [0 - 4095]
  LDRB  Wt, [base, Wm {,SXTW|UXTW {#0}} ]
  LDRB  Wt, [base, Xm {,LSL|SXTX  {#0}} ]

命令のエンコード
LDRB 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 0 0 1 1 1 0 0 0 0 1 0 simm9 0 1 Rn Rt
pre index 0 0 1 1 1 0 0 0 0 1 0 simm9 1 1 Rn Rt
LDURB 0 0 1 1 1 0 0 0 0 1 0 simm9 0 0 Rn Rt
unsigned 12 0 0 1 1 1 0 0 1 0 1 uimm12 Rn Rt
register 0 0 1 1 1 0 0 0 0 1 1 Rm option S 1 0 Rn Rt


[8] LDRSB 符号付きバイト(8ビット) → 32ビット

メモリから 8 ビットのデータを読み取って、32 ビットレジスタに 符号拡張して格納する命令です。 8ビットのデータが 負(最上位ビットが「1」)の場合には、32ビットレジスタの 上位24ビットをすべて「1」とします。8ビットで負の値は 32ビットでも同じ負の値となります。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDRB、LDRSB)があります。 使う機会はあまりないと思います。

  LDRSB  Wt, [base], #simm9     // ポストインデックス
  LDRSB  Wt, [base,  #simm9]!   // プレインデックス
  LDURSB Wt, [base,  #simm9]
  LDRSB  Wt, [base {,#uimm12} ]  // 符号なしオフセット [0 - 4095]
  LDRSB  Wt, [base, Wm {,SXTW|UXTW {#0}} ] 
  LDRSB  Wt, [base, Xm {,LSL|SXTX {#0}} ] 

命令のエンコード
LDRSB 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 0 0 1 1 1 0 0 0 1 1 0 simm9 0 1 Rn Rt
pre index 0 0 1 1 1 0 0 0 1 1 0 simm9 1 1 Rn Rt
LDURSB 0 0 1 1 1 0 0 0 1 1 0 simm9 0 0 Rn Rt
unsigned 12 0 0 1 1 1 0 0 1 1 1 uimm12 Rn Rt
register 0 0 1 1 1 0 0 0 1 1 1 Rm option S 1 0 Rn Rt


[9] LDRSB 符号付きバイト(8ビット) → 64ビット

メモリから 8 ビットのデータを読み取って、64 ビットレジスタに 符号拡張して格納する命令です。 8ビットのデータが 負(最上位ビットが「1」)の場合には、64ビットレジスタの 上位56ビットをすべて「1」とします。8ビットで負の値は 64ビットでも同じ負の値となります。 使う機会はあまりないと思います。 データより転送先レジスタが大きいため、符号の有無で2つの命令が 必要となりますが、8ビットから64ビットへの符号なし拡張(ゼロ拡張)はLDRB [7]と 同じ動作になるため、専用の命令はありません。

  LDRSB  Xt, [base], #simm9     // ポストインデックス
  LDRSB  Xt, [base,  #simm9]!   // プレインデックス
  LDURSB Xt, [base,#simm9]
  LDRSB  Xt, [base {,#uimm12} ]  // 符号なしオフセット [0 - 4095]
  LDRSB  Xt, [base, Wm {,SXTW|UXTW {#0}} ] 
  LDRSB  Xt, [base, Xm {,LSL|SXTX  {#0}} ] 

命令のエンコード
LDRSB 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
post index 0 0 1 1 1 0 0 0 1 0 0 simm9 0 1 Rn Rt
pre index 0 0 1 1 1 0 0 0 1 0 0 simm9 1 1 Rn Rt
LDURSB 0 0 1 1 1 0 0 0 1 0 0 simm9 0 0 Rn Rt
unsigned 12 0 0 1 1 1 0 0 1 1 0 uimm12 Rn Rt
register 0 0 1 1 1 0 0 0 1 0 1 Rm option S 1 0 Rn Rt


次はストア命令




このページの目次