Cortex-A8 (ARMv7-A, e.x. BeagleBone Black)のレジスタ情報/アセンブラ命令/インラインアセンブラの書き方
前書き:XINU (Real Time OS)で学んだARMに関する情報
本記事では、ARM CPU(Cortex-A8、32bit)に対する調査内容を備忘録としてまとめています。
ARMに関する調査は、XINUのソースコードを読むために実施しました。XINU (Xinu Is Not Unix )とは、パデュー大学のダグラス・カマーが教育目的で開発した Real Time OS であり、ARM Cortex-A8が搭載されたBeagleBone Black(シングルボードコンピュータ)上で動作します。
XINUは、Kernel空間とUser空間が分離していないシンプルな作りであり、OSを勉強したい人にはオススメです。
- 小規模( 約 1 万 LOC)
- 産業用途での使用実績がある事(= 実運用に耐えられる設計である事)
- C 言語の文法が古くない事(= 古い UNIX は小規模であるが、文法が古くて読みづらい)
- 副読書が存在する事(Xinu オペレーティングシステムデザイン 改訂 2 版)
以上を踏まえて、本記事では以下の内容を紹介します。
- XINUがKernelとして動作する時(例:デバイス操作時やシステムコール実行時)に操作するレジスタ情報
- ARM 32Bit命令
- インライアセンブラの書き方
ARM Coretex-A8/BeagleBone Blackリファレンス
本記事に書かれた内容は誤りが含まれる可能性があるため、より正確な情報を得るには、以下のテクニカルリファレンスや外部サイトをご参照ください。
ARM 32bit レジスタ一覧
ARM 32bitレジスタの中で、頻繁に使用するものを下表に示します。
引数の受け渡しにスタックのみを使うi386アーキテクチャと異なり、ARMでは汎用レジスタr0〜r3を使用して関数の引数を渡します(汎用レジスタが不足する場合はスタックを使用します)。返り値も汎用レジスタで返します。
レジスタ | 別名 | 役割 |
---|---|---|
r0 | a1 | 汎用レジスタ(引数の受け渡し、関数の返り値に使用) |
r1 | a2 | 汎用レジスタ(引数の受け渡し、関数の返り値に使用) |
r2 | a3 | 汎用レジスタ(引数の受け渡し、関数の返り値に使用) |
r3 | a4 | 汎用レジスタ(引数の受け渡し、関数の返り値に使用) |
r4 | v1 | 汎用レジスタ |
r5 | v2 | 汎用レジスタ |
r6 | v3 | 汎用レジスタ |
r7 | v4 | 汎用レジスタ |
r8 | v5 | 汎用レジスタ |
r9 | sb | 汎用レジスタ(静的データセグメントのベースアドレス) |
r10 | sl | 汎用レジスタ (スタックリミット) |
r11 | fp | 汎用レジスタ(フレームポインタ) |
r12 | ip | プロシージャ内呼び出しスクラッチレジスタ |
r13 | sp | スタックポインタ |
r14 | lr | リンクレジスタ(リターンアドレス) |
r15 | pc | プログラムカウンタ |
cpsr | – | カレントプログラムステータスレジスタ |
cpsr(カレントプログラムステータスレジスタ)
cpsr は、プロセッサの演算結果や動作モード・割り込み設定状態を保持するレジスタです。
Bit | 名称 | 役割 |
---|---|---|
31 | N | 演算結果が負の場合に設定される |
30 | Z | 演算結果が 0 の場合に設定される |
29 | C | 演算結果がキャリーアウトの場合に設定される |
28 | V | 演算結果がオーバフローの場合に設定される |
27 | Q | 飽和が発生した事を示す(自動クリアされない) |
26〜25 | IT | Thumb IT (If-Then)命令用のステータスを示す |
24 | J | プロセッサが Jazelle(※1) 状態かどうかを示す |
23〜20 | 予約 | 予約された Bit。 |
19〜16 | GE[3:0] | 演算結果が〇〇以上の場合に設定される(SIMD 命令で使用される) |
15〜10 | IT[7:2] | Thumb IT (If-Then)命令の状態を示す |
9 | E | ロード/ストア命令のエンディアン形式を設定する (0:リトルエンディアン、1:ビックエンディアン) |
8 | A | 非同期アボートマスクする場合に設定される |
7 | I | IRQ をマスクする場合に設定される |
6 | F | FIQ をマスクする場合に設定される |
5 | T | Thumb 命令の状態を示す |
4〜0 | M | モード領域 |
※1 Java 仮想マシンによるバイトコード実行時にハードウェアアクセラレーションのアーキテクチャサポートを提供する。Jazelle-DBX と Jazelle-RCT がある。
コプロセッサ一覧
プロセッサキャッシュや MMU の操作などでは、コプロセッサとコプロセッサ用レジスタを使用します。コプロセッサは 16 個存在します。
CP0〜9、CP12、CP13 は、システム独自の外部コプロセッサとして使用できます。その他のコプロセッサは、下表に示す通り、予め役割を定められています。
コプロセッサ | 役割 |
---|---|
CP10 | VFP(Vector Floating Point、単精度の浮動小数点)制御 |
CP11 | VFP(Vector Floating Point、倍精度の浮動小数点)制御 |
CP14 | デバッグおよび ETM(Embedded Trace Macrocell、実行命令履歴)制御 |
CP15 | システム制御 |
ARM 32bit 命令
命令 | 役割 |
---|---|
and | 論理積を取る |
orr | 論理和を取る。 |
bic | ビットをクリアする。 |
push | レジスタ値をメモリに保存する |
pop | レジスタ値をメモリから復元する |
mrs | ステータスレジスタから汎用レジスタに値を移す |
msr | 汎用レジスタからステータスレジスタに値を移す |
mrc | コプロセッサから汎用レジスタに値を移す |
mcr | 汎用レジスタからコプロセッサに値を移す |
mov | レジスタからレジスタに値を移動する |
str | レジスタからメモリに値を移動する |
ldr | レジスタからレジスタに値を読み込む |
b | PC 値にオフセットを加えたメモリアドレス(ラベル先)に分岐する。 |
bl | ラベル先へ分岐し、次の命令アドレスを r14(lr)にコピーする(※2) |
cpsie | I:IRQ 割り込みを許可、F:FIQ 割り込みを許可 |
cpsid | I:IRQ 割り込みを禁止、F:FIQ 割り込みを禁止 |
※2 指定の番地へ分岐する前に戻りアドレスを R14=LR に保存するため、lrの内容を pc に書き込むと(MOV PC,LR)、元に戻る。
IRQ/FIQ 割り込み
FIQは高い優先度の高速割り込みであり、IRQ は通常優先度の割り込みです。
FIQは、プロセッサが状態を保存しなくて良いハードウェアのために存在し、 割り込み要求の処理中に「IRQ」および「その他の FIQ ハンドラ」を無効にする事によって優先順位を付けています。FIQ ハンドラ処理中に、他の割り込みは発生しません。
- cpsr の I ビットが 0 および IRQ 端子が有効になった場合、IRQ 割り込み例外が発生。
- cpsr の F ビットが 0 および FIQ 端子が有効になった場合、FIQ 割り込み例外が発生。
ARMインラインアセンブラ(GCC)の書き方
インラインアセンブラとは、C 言語ソースコード中でアセンブラ命令を埋め込む機能です。インラインアセンブラの使用時に用いる命令は、下表の通りです。
命令 | 役割 |
---|---|
__asm__ | インラインアセンブラの使用開始を意味する |
__volatile__ | コードの最適化を抑制する。 |
構文は、__asm__(アセンブラコード :出力オペランド :入力オペランド :上書きされるレジスタリスト)という形式で、
“:”以降の指定は全てオプションです。記載例は、以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
int func(int *a) { int result = 0; __asm__ __volatile__ ( "mov r1, #99;" "str r1, [%1];" "mov %0, #88;" : "=r"(result) /* 出力オペランド。"=r"の後に(C言語の変数名)を記載する(オプション) */ : "r"(a) /* 入力オペランド・"=r"の後に(C言語の変数名)を記載する(オプション) */ : /* 上書きされるレジスタ。オプションなので無記載でも良い。記載する場合は"r2"、"r3"...と記載する。*/ ); /* 補足:アセンブラ命令の%n部分(nは正の数値)が入出力オペランド。数値は定義順に昇順で割り当てる。*/ return ret; } |
上書きされるレジスタには”memory”も指定でき、指定した場合は「インラインアセンブラの中で変数(レジスタ)が書き換わっている事」を明示しています。
つまり、”memory”はコンパイラに向けた宣言であり、「インラインアセンブラで変数が書き換わるので、それを踏まえて最適化してください」と伝えています
ただし、”memory”によってコンパイラレベルでの最適化はコントロールできますが、ハードウェアによる実行時並べ替え(Out of Order 実行)までは制御できません。
ロシア人と国際結婚した地方エンジニア。
小学〜大学院、就職の全てが新潟。
大学の専攻は福祉工学だったのに、エンジニアとして就職。新卒入社した会社ではOS開発や半導体露光装置ソフトを開発。現在はサーバーサイドエンジニアとして修行中。HR/HM(メタル)とロシア妻が好き。サイトに関するお問い合わせやTwitterフォローは、お気軽にどうぞ。
1件の返信
[…] […]