ARMv4Tについて個人的にまとめたものです。内容には間違いが含まれている場合があります。
呼び出し規約
- 呼び出し元:
- 第1引数から第4引数を
r0からr3に入れる
- 以降の引数をスタックに積む
- リンク付きでジャンプする(
bl)
- 呼び出し先:
push lr
- 呼び出し元のレジスタ状態を保存する
- 処理を行う
- 戻り値を
r0に入れる
- 呼び出し元のレジスタ状態を復元する
pop lr
bx lr
レジスタ
r0-r3は呼び出された側によって内容が維持されない
r4-r11は呼び出された側によって内容が維持される
| 番号 | 別名 | 用途 |
|---|
| r0 | a1 | 引数を渡す、計算を行う、戻り値を返す |
| r1 | a2 | 引数を渡す、計算を行う |
| r2 | a3 | 〃 |
| r3 | a4 | 〃 |
| r4 | v1 | 計算を行う |
| r5 | v2 | 〃 |
| r6 | v3 | 〃 |
| r7 | v4 | 〃 |
| r8 | v5 | 〃 |
| r9 | v6 | 〃 |
| r10 | v7 | 〃 |
| r11 | v8,fp | Frame Pointer. 呼び出された時点でのスタックの先頭へのアドレスを入れる |
| r12 | ip | Intra-Procedure-call scratch register |
| r13 | sp | Stack Pointer. スタックの先頭へのアドレスを入れる |
| r14 | lr | Link Register. リターン先へのアドレスが入る |
| r15 | pc | Program Counter. 実行するプログラムへのアドレスが入る |
ARM命令
表記法
| 名前 | 記法 | 説明 |
|---|
| 条件コード | {cond} | CPSRの条件コードフラグが指定の状態を満たしていれば、その命令を実行する |
| オペランド2 | <operand2> | 即値かレジスタから値を指定する。レジスタではシフト演算ができる |
| フィールド | {field} | PSRのビットマスクを指定する |
| 条件コードセット | S | 条件コードフラグを更新する |
| レジスタリスト | <reglist> | レジスタのリスト。{r0, r1, r2}と記述する |
条件コード cond
| 接尾辞 | 意味 | 条件 |
|---|
EQ | 等価 | Z == 1 |
NE | 非等価 | Z == 0 |
CS | 以上(符号なし) | C == 1 |
CC | 未満(符号なし) | C == 0 |
MI | 負数 | N == 1 |
PL | 非負数 | N == 0 |
VS | オーバーフロー | V == 1 |
VC | 非オーバーフロー | V == 0 |
HI | 大きい(符号なし) | C == 1 && Z == 0 |
LS | 小さい(符号なし) | C == 0 && Z == 1 |
GE | 以上 | N == V |
LT | 未満 | N != V |
GT | 大きい | Z == 0 && N == V |
LE | 小さい | Z == 1 | N != V |
AL | 常時 | true |
アドレッシングモード
モード2 <a_mode2>
通常
Rnにオフセット値を加えた値をアドレスとする
Rnは変化しない
| タイプ | 構文 |
|---|
| 即値オフセット | [Rn, #+/-12ビット数値] |
| レジスタオフセット | [Rn, +/-Rm] |
| レジスタオフセット(論理左シフト) | [Rn, +/-Rm LSL \#5ビット即値] |
| レジスタオフセット(論理右シフト) | [Rn, +/-Rm LSR \#5ビット即値] |
| レジスタオフセット(算術左シフト) | [Rn, +/-Rm ASR \#5ビット即値] |
| レジスタオフセット(右ローテート) | [Rn, +/-Rm ROR \#5ビット即値] |
| レジスタオフセット(拡張右ローテート) | [Rn, +/-Rm LSL \#5ビット即値] |
Pre-indexed
Rnにオフセット値を加えた値をアドレスとする
Rnはオフセット値を加えた値になる
| タイプ | 構文 |
|---|
| 即値 | [Rn, #+/-12ビット数値]! |
| レジスタ | [Rn, +/-Rm]! |
| レジスタ(論理左シフト) | [Rn, +/-Rm LSL \#5ビット即値]! |
| レジスタ(論理右シフト) | [Rn, +/-Rm LSR \#5ビット即値]! |
| レジスタ(算術左シフト) | [Rn, +/-Rm ASR \#5ビット即値]! |
| レジスタ(右ローテート) | [Rn, +/-Rm ROR \#5ビット即値]! |
| レジスタ(拡張右ローテート) | [Rn, +/-Rm LSL \#5ビット即値]! |
Post-indexed
Rnの値をアドレスとする
Rnはオフセット値を加えた値になる
| タイプ | 構文 |
|---|
| 即値 | [Rn], #+/-12ビット数値 |
| レジスタ | [Rn], +/-Rm |
| レジスタ(論理左シフト) | [Rn], +/-Rm LSL \#5ビット即値 |
| レジスタ(論理右シフト) | [Rn], +/-Rm LSR \#5ビット即値 |
| レジスタ(算術左シフト) | [Rn], +/-Rm ASR \#5ビット即値 |
| レジスタ(右ローテート) | [Rn], +/-Rm ROR \#5ビット即値 |
| レジスタ(拡張右ローテート) | [Rn], +/-Rm LSL \#5ビット即値 |
モード3 <a_mode3>
| タイプ | 構文 |
|---|
| 即値オフセット | [Rn, #+/-8ビット数値] |
| Pre-indexed | [Rn, #+/-8ビット数値]! |
| Post-indexed | [Rn], #+/-8ビット数値 |
| レジスタ | [Rn, +/-Rm] |
| Pre-indexed | [Rn, +/-Rm]! |
| Post-indexed | [Rn], +/-Rm |
オペランド2
| タイプ | 構文 |
|---|
| 即値 | \#32ビット即値 |
| 論理左シフト | Rm LSL \#5ビット即値 |
| 論理右シフト | Rm LSR \#5ビット即値 |
| 算術右シフト | Rm ASR \#5ビット即値 |
| 右ローテート | Rm ROR \#5ビット即値 |
| レジスタ | Rm |
| 論理左シフト | Rm LSL Rs |
| 論理右シフト | Rm LSR Rs |
| 算術右シフト | Rm ASR Rs |
| 右ローテート | Rm ROR Rs |
| 拡張右ローテート | Rm RRX |
フィールド
| 接尾辞 | 意味 | マスク |
|---|
_c | 制御フィールド | 0x000000ff |
_x | 拡張フィールド | 0x0000ff00 |
_s | ステータスフィールド | 0x00ff0000 |
_f | フラグフィールド | 0xff000000 |
移動
| 名前 | 構文 | 説明 |
|---|
| 移動 | MOV{cond}{S} Rd, <operand2> | <operand2>の値をRdに入れる |
| SPSRから移動 | MSR{cond} Rd, SPSR | SPSRの値をRdに入れる |
| CPSRから移動 | MSR{cond} Rd, CPSR | CPSRの値をRdに入れる |
| SPSRへ移動 | MSR{cond} SPSR{filed}, Rm | Rmの値をSPSRに入れる |
| CPSRへ移動 | MSR{cond} CPSR{filed}, Rm | Rmの値をCPSRに入れる |
算術
| 名前 | 構文 | 説明 |
|---|
| 減算 | SUB{cond}{S} Rd, Rn, <operand2> | Rnの値から<operand2>の値を減算してRdに入れる |
論理
| 名前 | 構文 | 説明 |
|---|
| 論理和 | ORR{cond}{S} Rd, Rn, <operand2> | Rnと<operand2>の論理和をRdに入れる |
| ビットクリア | BIC{cond}{S} Rd, Rn, <operand2> | <operand2>の値で指定したビットを0にしたRnの値をRdに入れる |
分岐
| 名前 | 構文 | 説明 |
|---|
| 分岐 | B{cond} label | labelにジャンプする |
| リンク付き分岐 | BL{cond} label | リンク付き分岐。復帰アドレスをr14にストアしてlabelにジャンプする |
| 分岐交換命令セット | BX{cond} Rn | CPUステートを切り替えてRnにジャンプする。Rnの1ビット目が0ならばARMステートに、そうでなければThumbステートに切り替わる。 |
ロード
| 名前 | 構文 | 説明 |
|---|
| ワード | LDR{cond} Rd, <a_mode2> | <a_mode2>が指すアドレスから32ビットをRdに読み出す |
| ハーフワード | LDR{cond}H Rd, <a_mode3> | <a_mode3>が指すアドレスから16ビットをRdに読み出す |
| ハーフワード(符号付き) | LDR{cond}SH Rd, <a_mode3> | <a_mode3>が指すアドレスから16ビットをRdに符号を考慮して読み出す |
| バイト | LDR{cond}B Rd, <a_mode2> | <a_mode2>が指すアドレスから8ビットをRdに読み出す |
| バイト(符号付き) | LDR{cond}SB Rd, <a_mode2> | <a_mode2>が指すアドレスから8ビットをRdに符号を考慮して読み出す |
| ブロック間転送(ポストインリメント) | LDM{cond}IA Rd{!}, <reglist>{^} | 各転送の後にアドレスをインリメントしながら複数のレジスタへ読み出す。!を付けるとRdに結果を書き戻す。(^はユーザーモードでは使わない) |
疑似命令
| 構文 | 説明 |
|---|
LDR{cond} Rd, =expr | exprの値が表現できる範囲内であれば、そのMOVかMVNを生成する。そうでなければ、exprの値をリテラルプールに配置してLDRを生成する。 |
LDR{cond} Rd, =label | labelの値をリテラルプールに配置してLDRを生成する。 |
ADR Rd, label | labelのアドレスをRdに入れる |
ストア
| 名前 | 構文 | 説明 |
|---|
| ワード | STR{cond} Rd, <a_mode2> | Rdの値を<a_mode2>が指すアドレスに32ビット分だけ書き出す |
| ハーフワード | STR{cond}H Rd, <a_mode3> | Rdの値を<a_mode3>が指すアドレスに16ビット分だけ書き出す |
| バイト | STR{cond} Rd, <a_mode2> | Rdの値を<a_mode2>が指すアドレスに8ビット分だけ書き出す |
| ブロック間転送(プレデクリメント) | STM{cond}DB Rd{!}, <reglist>{^} | 各転送の前にアドレスをデクリメントしながら複数のレジスタに書き出す。!を付けるとRdに結果を書き戻す。(^はユーザーモードでは使わない) |
スタック操作
| 名前 | 構文 | 説明 |
|---|
| プッシュ | PUSH <reglist> | レジスタは若い番号が後になるように積まれる。STMDBと同等。 |
| ポップ | POP <reglist> | レジスタは若い番号が先になるように取り出される。LDRIAと同等。 |
ソフトウェア割り込み
| 名前 | 構文 | 説明 |
|---|
| ソフトウェア割り込み | SWI 24ビット即値 | 指定のOSの機能をスーパーバイザーモードで実行する |
GAS
用語
- ロケーションカウンタ:物理的なアドレスを計算するための論理的なアドレス
- リテラルプール:即値で表現できない定数を持つ命令を扱うために必要なリテラルを配置するための領域
シンボル
ラベル
- 末尾が
:のシンボル
- 記述された位置でのロケーションカウンタを示す
ディレクティブ
| 構文 | 説明 |
|---|
.arm | 以下がARM命令であることを示す |
.align alignment, {fill=0}, {max=alignment} | alignmentで指定されるアライメントを満たすにようにロケーションカウンタを調整する。挿入された領域はfillで初期化される。挿入された領域がmaxバイトより大きい場合、アライメントされない。(alignmentはアーキテクチャによって、バイト数であったりマスクであったりする) |
.balign alignment, {fill=0}, {max=alignment} | alignmentのバイト数にアライメントされるようにロケーションカウンタを調整する。挿入された領域はfillで初期化される。挿入された領域がmaxバイトより大きい場合、アライメントされない。 |
.fill repeat, {size=1}, {value=0} | repeat個のsizeバイトの値valueで埋める |
.global symbol | symbolをリンカから見えるようにする |
.pool | リテラルプールを明示的に配置する |
{arg=default}は既定値defaultを持つ省略可能な引数argを示す
,は適宜省略できる