(since 1998/11)(更新 2004/02/26)

TNO2:CASL入門[12]

情報系/IT系の広告を掲載しています。(広告一覧)
©Copyright 1998-2001,2003,2004 小野智章(小野情報設計)
無断転載を禁止します。
本ページは、「Rook」仕様に対応済みです。
CASL入門[目次]
CASL入門[索引]
CASL入門[11]
CASL入門[13]

(chapter12-page1)
12-1.ループ・カウンタとリテラル

 先ほどのプログラムでは、 「SUBA」命令で繰り返し数(GR1)を1づつ減らしています。 この様なループ回数を数えるためのレジスタ等を、 「ループ・カウンタ」と呼びます。 逆に、0から始めて1づつ増やして行って何回実行したかを数える場合も、 「ループ・カウンタ」と呼びます。
 さて、先ほどのプログラムには、数値「1」を格納してある場所に付けられた 「ONE」と言うラベルが出てきました。 「SUBA」命令が、主記憶に格納してある値をレジスタから引く命令だからです。 しかし、 「定数」を格納する場所を、一々別に用意するのは面倒です。 CASLIIには、 「定数」を格納する場所を別に用意しなくても良い方法があります。
SAMPLE  START
  READ  0 ;SUM
  ST  GR0,VAL ; =VAL
  READ  1 ;COUNT
LOOP 
  SUBA  GR1,=1 ;COUNT−1
  JZE  LEND ;IF COUNT=0
  ADDA  GR0,VAL ;SUM+VAL
  JUMP  LOOP ;LOOP
LEND 
  WRITE  0
  EXIT
VAL  DS  1
  END
 「ONE」の代わりに「=1」が出てきました。 しかし、「=」と言う文字はラベルには使えませんでしたね。 しかも、定数「1」を格納していた「DC」命令の行が無くなっています。 「SUBA」命令は主記憶に格納してある値をレジスタから引く命令の筈なのに、 どうしたことでしょう。 レジスタ間演算でしょうか。
 実は、「=定数」と言う形式は、 オペランドに定数を格納した主記憶のアドレスを記述したい時、 その定数を格納した場所を用意してくれる表現なのです。 この書き方を「リテラル」と言います。 リテラルの「定数」の部分には、 10進数、16進数、文字定数が書けます。
(ラベルのリテラルは出来ません。 ラベルの示すアドレスは、 そのリテラルを記述した時点では確定していない場合があるためです。)

 一般的な注意として、 リテラルで用意された定数の格納場所の内容は、 プログラムで書き換えないでください。
 当然、書き換えた後は、格納内容はリテラルで示した値と異なってしまいます。 そのリテラルを使った命令を再実行した時は、 プログラムの見掛けと異なる値を指し示していることになるので、 混乱の元になります。 Rookではこれを防止するため、 「Alart時、停止」の機能を有効にしておくことで、 この様な書換えをしようとするとエラー停止する様になっています。 (又、プログラムの別の部分で同じ定数をリテラルで使用し、 指し示す格納アドレスが同じになっている場合は、 異常動作してしまいます。 又は、リテラルの異常な使用として、アセンブル・エラーになるかもしれません。)
 リテラルで用意された定数の格納場所の内容を書き換えるプログラムの例を、 参考までに示しておきます。
BAD  START
  LD  GR0,=65 ;’A’
  ST  GR0,OUTSTR ;String−Top
  OUT  OUTSTR,OUTLEN ;Output
  LAD  GR0,66 ;’B’
  ST  GR0,=65 ;Change ’A’
  LD  GR0,=65 ;’A’?
  ST  GR0,OUTSTR ;String−Top
  OUT  OUTSTR,OUTLEN ;Output
  EXIT
OUTSTR  DS  256
OUTLEN  DC  1
  END

(chapter12-page2)
 「ループ・カウンタ」を1づつ減らしてその結果をフラグで判定する、 別の方法もやってみましょう。
 旧CASLではこの様な場合、 「LEA GR1,−1,GR1」が常套手段でした。 しかし、CASLIIで対応する「LAD」命令では、 レジスタの値が変化しても、フラグが変化しません。 代わりに、CASLIIでは、 新しく「LD」命令でフラグが変化する様になりました。 そこで、結果のレジスタの値を直接判定することにします。
 先ほどのSAMPLEプログラムの「SUBA」の1行を、 次の2行で置き換えてください。
   LAD  GR1,−1,GR1 ;COUNT−1
   LD  GR1,GR1 ;Check COUNT
 同じレジスタ間でロードを実行することで、 レジスタの値を変化させることなく、 フラグを変化させています。 即ち、GR1の値の正・0・負が、フラグに設定されます。 この方法は、 CASLIIでのレジスタの値の正・0・負の判定方法となりますので、 憶えておきましょう。

 どちらの方法が良いかという判断は、 視点によって異なってきます。 使用する主記憶と実行速度については、 処理するコンピュータやエミュレータにもよりますが、 通常は同等と推定出来ます。 (命令数の差によって、命令デコード時間の影響が若干あるかもしれません。) 表現が簡単な分、前のリテラルを使う方法が良いと思われるので、 今後はリテラルの方法を使用していくことにします。

(chapter12-page3)
12-2.分岐命令と判断

 今までの分岐命令は、ループとループの終了のために使っていました。 しかし、「JUMP」以外の分岐命令は、 フラグ・レジスタの内容によって動作が変わりますから、 条件の判断に使えます。
SAMPLE  START
  READ  1 ;SUM
  LD  GR1,GR1 ;CHECK GR1
  JMI  MINUS ;IF GR1<0
  JZE  ZERO ;IF GR1=0
PLUS
  OUT  PSTR,PLEN
  EXIT
MINUS
  OUT  MSTR,MLEN
  EXIT
ZERO
  OUT  ZSTR,ZLEN
  EXIT
PSTR  DC  ’PLUS’
PLEN  DC  4
MSTR  DC  ’MINUS’
MLEN  DC  5
ZSTR  DC  ’ZERO’
ZLEN  DC  4
  END
 「LD」命令でGR1をチェックしています。 GR1の値は変化していないことに注意して下さい。 その結果が負なら「MINUS」へ、0なら「ZERO」へ、 正ならそのまま下の「PLUS」へ、プログラム・レジスタを移動します。 (実際には、「PLUS」のラベルは不要です。 説明の都合と分かり易くするために、付けました。)
(chapter12-page4)
 それぞれの場合に、対応した文字列を「OUT」命令で表示して、 「EXIT」命令でプログラムの実行を終了します。

 プログラムを実行してみて下さい。 入力した数値に応じて、メッセージが表示されますね。
Input : GR1 = 5(0005)
PLUS
プログラムは、PR[000F;SAMPLE+15]が指定したEXIT命令で終了しました。
Input : GR1 = -7(FFF9)
MINUS
プログラムは、PR[0017;SAMPLE+23]が指定したEXIT命令で終了しました。
Input : GR1 = 0(0000)
ZERO
プログラムは、PR[001F;SAMPLE+31]が指定したEXIT命令で終了しました。

 さて、このプログラムでは「EXIT」命令が3ケ所に出てきています。 一般に、この様な終了を表す命令は、 1ケ所にまとめた方が良いと言われています。 どの様にプログラムを変更すれば良いか、確かめておいて下さい。

CASL入門[目次]
CASL入門[索引]
CASL入門[11]
CASL入門[13]
学習室
トップ・ページへ

質問・ご意見等、お待ちしております。
小野智章(小野情報設計) 
Mail to Mail連絡先
©Copyright 1998-2001,2003,2004 小野智章(小野情報設計)
無断転載を禁止します。