CASL U - 10倍の計算 |
数値データの10倍を計算する副プログラム(サブプログラム)を作成する。 COMETUは1語16ビットであり、扱える数値の範囲は−32768〜32767なので、元の数値データは1/10の
−3276〜3276 とする。
この副プログラム(M10)は、元の値nをGR1に格納して呼び出し、結果もGR1に格納して戻るものとする。
10倍の計算方法
元の数値をnとする。n×10を求めたいが乗算の命令はない。加算命令でnを10回加える方法もあるが、ここではシフト命令と加算命令で10倍を計算する。
左シフト命令では2倍、4倍、8倍、16倍、… が計算できる。
10n = n + n + n + n + n + n + n + n + n + n
= 2n + 2n + 2n + 2n + 2n … @
= 4n + 4n + 2n … A
= 8n + 2n … B
= 2(4n + n) … C
計算量は少ないほど良いので、BCで考えてみることにする。
方法B 8n + 2n
GR1 ← GR1を1ビット左シフト (GR1=2n)
GR2 ← GR1 (GR1=2n, GR2=2n)
GR1 ← GR1を2ビット左シフト (GR1=8n, GR2=2n)
GR1 ← GR1+GR2 (GR1=10n, GR2=2n)SLA
LD
SLA
ADDAGR1, 1
GR2, GR1
GR1, 2
GR1, GR2
方法C 2(4n + n) = 2(5n)
GR2 ← GR1 (GR1=n, GR2=n)
GR1 ← GR1を2ビット左シフト (GR1=4n, GR2=n)
GR1 ← GR1+GR2 (GR1=5n, GR2=n)
GR1 ← GR1を1ビット左シフト (GR1=10n, GR2=n)LD
SLA
ADDA
SLAGR2, GR1
GR1, 2
GR1, GR2
GR1, 1
手順ができあがるとプログラムもほぼできあがりである。GR1以外にGR2を使っているので、GR2はスタックを使って値を保存しておく。
M10 START PUSH 0, GR2 ;GR2の値をスタックに保存. <<処理>> POP GR2 RET END
<<処理>>の部分を方法Bまたは方法Cのプログラムに置き換えれば完成である。プログラムリストを次に示す。
緑色の部分がメインのプログラムである。ここでは、(1)GR1にDATA番地の内容を格納し、(2)副プログラムM10を呼び出し、(3)GR1の内容(結果)をANS番地に格納している。
方法B
MAIN1 START
LD GR1, DATA
CALL M10 ;10倍の計算.
ST GR1, ANS
RET
DATA DC 10
ANS DS 1
END
M10 START ;GR1 の値を10倍する.
PUSH 0, GR2
SLA GR1, 1 ;2倍(2n=n*2).
LD GR2, GR1 ;2nをGR2に格納.
SLA GR1, 2 ;4倍(8n=2n*4).
ADDA GR1, GR2 ;2nを加算(10n=8n+2n).
POP GR2
RET
END
方法C
MAIN1 START
LD GR1, DATA
CALL M10 ;10倍の計算.
ST GR1, ANS
RET
DATA DC 10
ANS DS 1
END
M10 START ;GR1 の値を10倍する.
PUSH 0, GR2
LD GR2, GR1 ;元の値nをGR2に格納.
SLA GR1, 2 ;4倍(4n=n*4).
ADDA GR1, GR2 ;元の値を加算(5n=4n+n).
SLA GR1, 1 ;2倍(10n=5n*2).
POP GR2
RET
END
DATA番地に元になる値を設定して実行するとANS番地に結果が記憶される。
方法BCのMAINのプログラムでは計算する値をDATA番地に記憶している。一般的には計算等の処理に使用するデータはラベルで定義する(DC命令)。このようにすればデータの変更が必要な場合でもラベルを探すことで、修正が容易になる。 CASLUではリテラルが使えるので LD GR1, =10 という書き方ができる。しかし、プログラムの中でデータを定義すると何のデータなのかわからなくなる可能性も出てくる。最小限にとどめておく方が良い。方法BCのMAIN程度なら次のようにリテラルを使用しても良いだろう。 MAIN1 START
LD GR1, =10
CALL M10 ;10倍の計算.
ST GR1, ANS
RET
ANS DS 1
END
アセンブルして機械語にするとメモリの使用量はどちらも同じであるが、命令行が1行節約できる。また、同じような機能の命令にLAD命令がある。 LAD GR1, 10 と書いても同じである。これもリテラルと同じように多用すると不明なデータとなる可能性があるので最小限にとどめておく方が良いだろう。メモリの使用量はラベル定義分だけ少ない。この命令を使って良くされることは LAD GR1, 0 のようにレジスタの初期化(0にする)である。
|
※ この10倍の計算の副プログラムは文字列データとして入力した数字列を数値に変換するときなどに利用できる。
課題1 16倍を計算する副プログラムM16を作成する。
元のデータをGR1に記憶させて副プログラムM16を呼び出す。結果はGR1に格納する。
課題2 10倍を計算する副プログラムM10にエラー処理を追加する。
正しく計算できる範囲は−3276〜3276である。GR1に格納されたデータが−3276〜3276の範囲にあるかどうかを確認し、範囲内であれば10倍を計算する。
元のデータが−3276〜3276の範囲になければエラーの値をGR1に格納して戻るようにする。10倍すると−32760〜32760の範囲の値になるので、エラーの値は32760(7FF8(16))より大きい7FFF(16)とする。FFFF(16)は-1で使えない。8000(16)は-32768なので使える。
エラーの値 = #7FFF
CASL U | Copyright © 2003,2017 Hiroshi Masuda |