2015年9月10日木曜日

ARMのプログラム技法

前回のブログでCalのプログラムの核心の部分がうまく書けることが分かったので, 全体を書いてみた. やや長いが興味があれば追ってみて欲しい.

プログラム0


行00 .data ここからデータ領域という指示
行01,02 年と月を格納する場所 4バイトずつ
行03 1月から順に次の年初の曜日とその月の1日の曜日の差 12月は31日なので 4週と3日余るが, -3mod7=4のような値のリスト. 以下rsという
行04 各月の長さ. 以下msという
行05〜09 scanf, printfの書式
行10 プログラム部分の開始
行11〜17 除算サブルーチン r0をr1で割り商をr0, 剰余をr1に置く

プログラム1


行19 主ルーチンの入り口, 帰り番地をr8へ退避する
行20 yearを入れる場所をr1へ
行21 monthを入れる場所をr2へ
行22 scanfの書式の番地をr0へ
行23 scanfを呼ぶ
行24 データ領域のベースアドレスをr3へ
行25 yearをr0へ
行26 400をr1へ
行27 除算
行28 400で割った剰余R400をr4へ
以下 R400を100と4で割った商と剰余を求める
行38 100で割った剰余を0と比較
それが0か否かにより, 400と4との剰余をr1に置く(条件つきmov)
行41 r1が0なら閏年(閏年の判定には100で割った剰余R100が0なら400で割った剰余R400が0, 0でないなら4で割った剰余R4が0かで判定できる)

プログラム2


行42〜47 r1=0なら閏年なので, rsの1月2月とmsの2月を修正する
行48〜58 その月の1日の週日(a)は(1+R400-Q100+Q4+rs[月])mod 7
行59 前回のブログのr5の値, 1-a
行60 前回のブログの#6に相当する値, 43-a
行62 前回のブログの#3に相当する値, その月の日数

プログラム3


出力用の値が設定できたので出力に移る.
行63,64 曜日の名を出力
行65 r4は1週間を数えるカウンタ
行66 日付が1より大きいか
行67 そうなら最後の日付より小さいか
行68 日付をr1に置く
行69,70 比較の結果でいづれかの書式をr0に置く
行72 日付を1増やす
行73 週のカウンタを減らす
行74〜76 1週間が終わったら改行しカウンタをリセット
行77,78 最後になっていなければl0へ戻る
行79 lrを戻す
行80,81 プログラムの戻り値を入れて終わる
行82〜87 定数の番地

このプログラムでは, データの場所にはラベルがあるが, プログラムの部分には殆どラベルが見られない. divmodはサブルーチンの入り口, mainはプログラム全体の入り口, あとカレンダー出力のループのl0があるだけである. 従ってジャンプ命令もほとんどない. そういうことではARMのアーキテクチャは気持ちがいいといえる.

このプログラムをRaspberry Piで動かすには,
as -o cal.o cal.s
gcc -o cal cal.o
./cal
で起動し
2015 9
のように年と月を入力すると
./cal
2015 9
 Su Mo Tu We Th Fr Sa
        1  2  3  4  5
  6  7  8  9 10 11 12
 13 14 15 16 17 18 19
 20 21 22 23 24 25 26
 27 28 29 30

とカレンダーが得られる.

このプログラムはhttp://www.iijlab.net/~ew/cal.sに置いてある.

0 件のコメント: