(since 1998/11)(更新 2012/02/19)
©Copyright 1998-2004,2012 小野智章(小野情報設計)
無断転載を禁止します。
本ページは、「Rook」
2.70に対応済みです。
さて、今まで色々なプログラムを作ってきましたが、
中には、何度も利用しそうな機能を持ったものもありました。
例えば、掛け算などは、色々な場面で何度も使われ
そうです。CASLIIには、その様な良く使う機能のプログラムを1度書けば、
何度もその機能を使える様にする
「サブルーチン」という仕組みがあります。
以前保存しておいた掛け算のソース・プログラムを、
「2-3章」に示す方法によって読み出して、
次の様に修正して下さい。
SAMPLE | | START |
| | READ | | 0 |
| | READ | | 1 |
| | CALL | | MUL | ;GR0=GR0*GR1 |
| | WRITE | | 0 |
| | EXIT |
MUL |
| | ST | | GR0,VAL | ;VAL |
LOOP |
| | SUBA | | GR1,=1 | ;COUNT−1 |
| | JZE | | LEND | ;IF COUNT=0 |
| | ADDA | | GR0,VAL | ;SUM+VAL |
| | JUMP | | LOOP | ;LOOP |
LEND |
| | RET |
VAL | | DS | | 1 |
| | END |
|
実行してみて、終了アドレス以外は、
元のプログラムと同じ結果が出てくることを確認して下さい。
元のプログラムと比べると、掛け算を行う部分が次の様に分離され、
「MUL」というラベルが付けられています。
また、掛け算を行う部分が取り出された後の場所には、
「CALL MUL」という行が、代わりに入っています。
この「MUL」というラベル以降の部分は
「サブルーチン」と呼ばれ、
「RET」命令
までがその範囲になります。
また、サブルーチンの始まりに付けられたラベルを
「サブルーチン名」と呼び、
その機能の名称として使います。
サブルーチンの機能を使う時には、
「CALL」命令で
その使いたいサブルーチンの始まるアドレスをラベルなどで指定してやります。
「CALL」命令でサブルーチンの機能を使うことを、
「サブルーチンを呼び出す
(callする)」といいます。
サブルーチンを部下に喩えるならば、
「呼び出す」ことで
その部下が自分の仕事を始める、といった意味合いになります。
「サブルーチン」に対して、上司に当るプログラムは、
主となる仕事という意味で
「メイン・ルーチン」と呼ばれます。
サブルーチンの終わりは、
「RET」命令で表します。
「RET」命令の動作を、
「サブルーチンから戻る
(returnする)」と言います。
部下(サブルーチン)の仕事が終わって、
上司(「CALL」命令のあるプログラム部分)の仕事の続きに戻る、
といった意味合いです。
実行の様子は次の様になります。
- GR0,GR1にデータを入力した後、
「CALL」命令で「MUL」サブルーチンを呼び出します。
これで、プログラム・レジスタに「MUL」のアドレスが入ります。
- プログラム・レジスタに入っている
「MUL」のアドレスから始まる掛け算の動作をします。
- 「RET」命令で、プログラム・レジスタに先ほどの「CALL」命令の
次の命令のアドレスが入ります。
- 「CALL」命令の次の命令から続きの実行をします。
この様に「CALL」命令も「RET」命令も、
プログラム・レジスタの内容を変えてしまうので、
「JUMP」命令の様な分岐命令の一種と考えることも出来ます。
この章の内容は、
学習に便利な様に、Rookに追加した機能についてのものです。
将来、仕様や実現形態が変更になる可能性があります。
作成したサブルーチンは、どの様にして保存するのでしょうか?
もちろん、通常のプログラムと同じく、
ソース・プログラムやオブジェクト・プログラムとして保存が可能です。
しかし、そのサブルーチンを別のプログラムで利用しようとする場合、
元のソース・プログラムを元に書き直すのは大変です。
特に、必要なサブルーチンが別々のソース・プログラムに別れている時は、
困ってしまいます。
そこで、Rookでは、
ソース・プログラムの形で別に保存したサブルーチンを、
アセンブルする時に自動的に取り込んでくれる機能を追加しています。
但し、この機能は、本来のCASLIIには含まれていません。
多くのアセンブル言語で採用されている便利な機能なので、
一般知識として理解出来る様に、付け加えています。
尚、Rookではファイル・アクセスが出来ないため、
普通とは多少異なる形式を採っています。
又、将来、仕様を変更する可能性があります。
まず、先ほどのプログラムをファイルへ保存した後、
サブルーチンを取出します。
「コピー&ペースト」機能を使うのが便利です。
(サブルーチン内のみで使われる「VAL」の行も含んでいます。)
MUL |
| | ST | | GR0,VAL | ;VAL |
LOOP |
| | SUBA | | GR1,=1 | ;COUNT−1 |
| | JZE | | LEND | ;IF COUNT=0 |
| | ADDA | | GR0,VAL | ;SUM+VAL |
| | JUMP | | LOOP | ;LOOP |
LEND |
| | RET |
VAL | | DS | | 1 |
|
このサブルーチン・プログラムを、
インクルード・テキストとして入力しなければなりません。
(一般のアセンブラでは、
この部分を別のファイルとして保存することになります。)
それでは、「Rook」画面中の、次の様な内容の左フレーム内の、
「Include-File」ボタンをクリックしてください。
これで、インクルード・テキストを入力出来るページが、
右フレームに表示されます。
操作方法は、ソース・プログラムと同様です。
次に、先ほど保存した元のソース・プログラムから、
サブルーチンを記述していた部分を取り除きます。
この操作は、ソース・プログラム入力画面中で行ってください。
SAMPLE | | START |
| | READ | | 0 |
| | READ | | 1 |
| | CALL | | MUL | ;GR0=GR0*GR1 |
| | WRITE | | 0 |
| | EXIT |
| | INCLUDE |
| | END |
|
このプログラムをアセンブルすると、
「INCLUDE」命令行のある位置に、
インクルード・テキストの内容と同じものがあると見なしてくれます。
(一般のアセンブラでは、
インクルード・テキストを格納したファイル名を指定します。)
正常にアセンブルされたら、実行してみて、
正しい結果が得られることを確認して下さい。
尚、「INCLUDE」命令を使用したプログラムでは、
アセンブル時にエラーが発生した場合に注意が必要です。
見えているプログラム部分のミス以外に、
インクルード・テキストの内容にミスがあることがあります。
この様に「INCLUDE」命令は、
指定されたインクルード・テキストの内容を取り込む機能を持っています。
「INCLUDE」命令は、
サブルーチンであるかどうかに係わらず
インクルード・テキストの内容を取り込むので、
良く使うテーブルや文字列、プログラムのパターンなどを、
インクルード・テキストにして保存しておくと便利です。
この章の内容は、
学習に便利な様にRookに追加する計画のある機能についてのもので、
現在は実現出来ていません。
又、実現形態も変更になる可能性があります。
先ほどは、サブルーチンをソース・プログラムの形で、保存しました。
ということは、
サブルーチンの部分を毎回アセンブルするということになり、無駄です。
多くのアセンブラでは、この無駄を省く目的で、
別々にアセンブルしたサブルーチンをオブジェクト・プログラムとして保存しておいて、
後でまとめてくっつける「リンク」という機能を利用します。
但しこの機能は、
本来のCASLIIでは使用方法などが明確には決められていません。
この機能も多くのプログラム言語で採用されており、
一般的なプログラム言語の学習の便のために、付け加える予定です。
では実際に、別々にアセンブルしたプログラムをリンクしてみましょう。
まず、先ほどのプログラム「MULT.CS」を保存した後、
INCLUDEファイル「MUL.CI」に記録されているサブルーチンを読出して、
次の様に修正します。
MUL | | START |
| | ST | | GR0,VAL | ;VAL |
LOOP |
| | SUBA | | GR1,=1 | ;COUNT−1 |
| | JZE | | LEND | ;IF COUNT=0 |
| | ADDA | | GR0,VAL | ;SUM+VAL |
| | JUMP | | LOOP | ;LOOP |
LEND |
| | RET |
VAL | | DS | | 1 |
| | END |
|
「START」
「END」を付け加えています。
この2つの命令を付け加えることで、アセンブルが可能になります。
「START」命令に付けられたラベルが
「MUL」になっていることに注意して下さい。
この「START」命令に付けられたラベルを、
CASLIIでは「入口名」といい、
リンクする時のラベルの目印となります。
このサブルーチンのオブジェクト・プログラムを、
「MUL.CO」というファイル名で保存します。
又、念のためにソース・プログラムも、
「MUL.CS」というファイル名で保存しておきます。
(「MULT.CS」ではないことに注意。)
今度は、先ほど保存した元のプログラム「MULT.CS」を読出し、
INCLUDE命令を削除します。
SAMPLE | | START |
| | READ | | 0 |
| | READ | | 1 |
| | CALL | | MUL | ;GR0=GR0*GR1 |
| | WRITE | | 0 |
| | EXIT |
| | END |
|
このプログラムをアセンブルすると、
次の様なアセンブル結果のメッセージと共に、
サブルーチンの無いオブジェクト・プログラムが出来上がります。
START = [SAMPLE]
Normal Asseble Finish.
in−source−Link Start.
Undefined Label : MUL
Link Nomal End.
Asseble End.
|
「Undefined Label : MUL」の部分は、
「MUL」というラベルが見つからない、という意味です。
この様にラベルが見つからないことを、
「ラベルが未定義である」
といいます。
その他は、正常にアセンブルされたことを表しています。
未定義のラベルがある以外は正常にアセンブルされたら、実行してみて下さい。
次の様なメッセージが表示されるはずです。
Undefined−Label[MUL] Exist!
|
このメッセージも、
オブジェクト・プログラムは存在しているが、
「MUL」という未定義のラベルがある、という意味です。
それでは、サブルーチン「MUL」のオブジェクト・プログラムを
リンクしてみましょう。
次の様にコマンドを入力して下さい。
次の様な表示が出れば、正常です。
Link Label[MUL]
file[MUL.CO] link ok!
|
サブルーチン「MUL」が入っているオブジェクト・プログラムをリンクすることで、
未定義だったラベル「MUL」のアドレスが決定されます。
このリンクによって決定出来るラベルは、
「入口名」となっているラベルに限られます。
リンクした後では、正常にプログラムを実行することが出来ることを確認して下さい。
INCLUDEの時と同じく、エラーが発生した場合、
見えているプログラム部分のミス以外に、
「MUL.CO」にミスがあることがあります。
今までは1つのサブルーチンしかリンクしませんでしたが、
幾つものサブルーチンをリンクすることも可能です。
便利な機能を持ったサブルーチンを沢山用意しておくと、
プログラムの作成が楽になりますね。
便利な機能を持ったサブルーチンを集めたものを
サブルーチン・ライブラリと呼びます。
誰もが良く使う機能はアセンブラやコンパイラのメーカが標準ライブラリとして用意してあり、
利用者固有のものはユーザ・ライブラリとして自作することになります。
尚、メイン・ルーチンをオブジェクト・プログラムとして保存しておけば、
ソース・プログラム無しでリンクすることも可能です。
この場合は、メイン・ルーチンの入ったオブジェクト・プログラムを
最初に読み出しておく必要があります。
これは、プログラムの実行開始アドレスが、
最初のオブジェクト・プログラムのSTARTで指定したアドレスになるからです。
更に、1つのオブジェクト・プログラム中のサブルーチンから
別のオブジェクト・プログラム中のサブルーチンを呼ぶことも可能です。
この様な場合は、プログラムの実行開始アドレスから始まるプログラムだけが
メイン・ルーチンと呼ばれ、
他のサブルーチンを呼び出す様なサブルーチンは
メイン・ルーチンとは呼ばれません。
大本の「主となるプログラム」だけが
「メイン・ルーチン」です。
ところで、ソース・プログラムをアセンブルしたオブジェクト・プログラムは、
リンクが不要であれば、今までそのまま実行出来ました。
これは、Rookのオブジェクト・プログラムが
そのまま実行可能な機械語のプログラムになっていたからです。
しかし、通常のアセンブラやコンパイラでは、
オブジェクト・プログラムはそのままでは実行出来ません。
未定義のラベルが無くてもリンク作業をして、
プログラムを実行可能な形式に変換する必要があります。
本システム以外のアセンブラやコンパイラを利用する時は、
十分気を付けて下さい。
質問・ご意見等、お待ちしております。
小野智章(小野情報設計)
Mail to
Mail連絡先
©Copyright 1998-2004,2012 小野智章(小野情報設計)
無断転載を禁止します。