2009年3月18日水曜日

個人用電卓のプログラミング

昨年10月頃, このブログに書いた個人用電卓は, 機能を拡張したヴァージョンが, シミュレータ上で快適に稼働している.

今回はそのプログラミング技法を紹介する.

Schemeで書いたシミュレータは, スタックの代りにリストを使う. car側がスタックトップである. 電卓実機はスタックを突き破ってポップも出来るが, リストではそうはいかぬ. また実機は2の補数の64ビットであったが, シミュレータはbignumである.

シミュレータには押しボタンはないから, それに相当する文字を決める.
0〜9は文字も09.
十六進のA,B,...,Fは小文字でa,b,...,f.
算術演算+,-,*,/はそのまま.
基数変換Hex, Dec, OctはH,D,O.
数値を区切るEntはE.
Pop, Dup, Exc, Chsはそれぞれ ^,",:,_.
Sqt, Fct, Pow, JDはそれぞれS,F,P,Jである.

従って3*(2+1)は, 3E2E1+* と入力する. リターンは無視.

拡張機能には, まず補助スタックが出来た. これも実態はリストである.
命令は2個

U スタックをポップし, そこにあったものを補助スタックにプッシュする.
N 補助スタックをポップし, そこにあったものをスタックにプッシュする.

こうすることで, 例えばスタックトップの4個を回転する:
:U:U:NN(d c b a ...)(c b a d ...)とすることが出来る. まず:でスタックは(c d b a ...)になる; Ucは補助スタックへ移り, (... c) (d b a ...)になる. 左側にあるリストが補助スタックで, スタックトップが右に書いてある. 2番目の:でスタックは(b d a ...)になり, U(... c b) (d a ...)になり, 3番目の:(a d ...)になり, NN(... ) (c b a d ...)になるのである.

こんなことをやっている内に, このプログラム列を記憶し, 繰り返し使いたくなった. そこで (:U:U:NN)R= と入力して, プログラム列をRという名前で記憶する. R(d c b a ...)(c b a d ...)になるので, RRRとすると(d c b a ...)がこの4段の回転を3回実行し, (a d c b ...)になるのである.

さらに欲が出てきて, プログラムの中で条件ジャンプがしたくなった.

G スタックのトップから2段目が負なら, スタックトップの数だけプログラムを戻る.

10から1までの和を計算するプログラムは次のようだ.

(0Ua"N+U1-"_aG^N)X=

と定義し, Xで起動する. 実行の様子は下の通り.



上の図では, 左の方に命令が縦に並べてある. 一番左の下から0,1,...とあるのは, G命令でジャンプする相対番地である. 10回目でループを抜けると, 主のスタックトップに和の55が出来ている.

ここまで来れば鬼に鉄棒である. もっと難しいプログラムの例はまた次回に.

0 件のコメント: