概要
SHARP Brain でアセンブラを使う
as
アセンブラは 拡張子が .s。
そのまま gcc に食わせて自動で as を判別してもらおう。
Makefile に追加したのは以下のとおり。
Makefile
AS = gcc
AFLAGS =
.SUFFIXES: .s.o
.s.o:
$(AS) $(AFLAGS) -c -o $@ $<
GAS の文法
ARM 純正な書き方に慣れているとミスるのでメモ
- シフタの前にカンマが必要 (省略してはいけない)
- コメントは @
- ローカル ラベルは数字
- 参照は 数字+b や 数字+f を付ける
平方根を求めるコード
unsigned int miyu_sqrt(unsigned int v)
.text
.global miyu_sqrt
miyu_sqrt:
mov r12, #0 @ a: r12
mov r1, #1 @ one
mov r2, #30 @ bit: r2
1: add r3, r1, r12, lsl #2 @ t = 4a + 1
mov r12, r12, lsl #1 @ a <<= 1
cmp r0, r3, lsl r2 @ n と (t << bit) を比較
addcs r12, r12, r1 @ n >= (t << bit) なら a++
subcs r0, r0, r3, lsl r2 @ n >= (t << bit) なら n -= (t << bit)
subs r2, r2, #2 @ bit -= 2 して フラグを更新
bpl 1b @ bit >= 0 なら 1: へジャンプ
mov r0, r12 @ 戻り値を設定
bx lr
.end
プロジェクトはこちら: https://gitlab.com/nekodevteam/brainux/-/tree/main/astest
ARM について
- PW-SH1 に乗ってるのは ARM926EJ-S (Armv5TEJ)
- ARM9E 200 MHz で ニンテンドーDS のメインCPU の兄弟
- 特色
- 命令は 4バイト長、Thumb という 2バイト長命令セットもあり
- 切り替えは PC のビット0 で切り替えを行う
- 切り替え時は bx命令 でジャンプする
- PC が偶数なら ARM コードを実行
- PC が奇数だったら (PC - 1) を Thumb コードとして実行
- ARM 命令セットの特徴
- 演算とシフトを同時実行できる
- 命令に実行条件が付けられる
- 演算命令ごとにフラグを更新するかしないかを選択できる
- 除算命令がない
- 命令は 4バイト長、Thumb という 2バイト長命令セットもあり
gcc とのやりとりについて
- r0, r1, r2, r3, r12 が caller-save レジスタ (.s で壊してよいレジスタ)
- そのほかは callee-save レジスタなので退避が必要
- C言語の引数は r0, r1, r2, r3 の順に割り当て、残りはスタック
- C言語への戻り値は r0 (とr1)
- gcc は ARMコードなので リターンは bx lr ではなく、mov pc, lr で良い