CASL U - 10倍の計算
 前へ 目次へ 次へ

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
ADDA    
GR1, 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    
SLA
GR2, 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にする)である。
      LD    GR1, DATA
      …
DATA  DC    10
      LD    GR1, =10
      LAD   GR1, 10
3つとも働きは同じ。LDA命令のメモリ使用量が少ない。

 ※ この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

 

 

inserted by FC2 system