(since 1998/11)(更新 2005/01/24)
©Copyright 1998-2001,2003-2005 小野智章(小野情報設計)
無断転載を禁止します。
本ページは、「Rook」1.40仕様に対応済みです。
シフトは、2進数で1桁ずらす命令でした。
実際のコンピュータの利用では、
10進数として1桁ずらしたい事の方が多いです。
10倍する方法を考えてみましょう。
まず、単に10回足し算をする方法です。
SAMPLE | | START |
| | READ | | 0 |
| | ST | | GR0,VAL | ; VAL |
| | ADDA | | GR0,VAL | ; VAL×2 |
| | ADDA | | GR0,VAL | ; VAL×3 |
| | : | | : | : |
| | ADDA | | GR0,VAL | ; VAL×10 |
| | WRITE | | 0 |
| | EXIT |
VAL | | DS | | 1 |
| | END |
|
プログラムは、同様の行が続くので、一部省略しています。
次の結果は、「55」と入力した場合の実行例です。
(「READ」命令では、
「55」は1つの数値として入力されます。
「IN」命令の様に文字2つとして入力されるのでは、ありません。)
Input : GR0 = 55(0037)
GR0=550(0226)
プログラムは、PR[001C;SAMPLE+28]が指定したEXIT命令で終了しました。
|
正しく10倍されますね。
しかし、10倍するのに10行も使っては効率が悪いです。
シフトを利用して10倍する方法を考えてみましょう。
2倍はシフトで出来ましたね。これで4行減ります。
もう少し、工夫してみましょう。
4倍もシフトで出来ます。これで、やってみましょう。
次のプログラムの空欄を埋めて下さい。
SAMPLE | | START |
| | READ | | 0 |
| | ST | | GR0,VAL | ; VAL |
| | □□□ | | GR0,□□□ | ; GR0=VAL×4 |
| | □□□ | | GR0,□□□ | ; GR0=VAL×5 |
| | □□□ | | GR0,□□□ | ; GR0=VAL×10 |
| | WRITE | | 0 |
| | EXIT |
VAL | | DS | | 1 |
| | END |
|
Input : GR0 = 55(0037)
GR0=550(0226)
プログラムは、PR[0010;SAMPLE+16]が指定したEXIT命令で終了しました。
|
プログラム中のコメントがヒントになっています。
[空欄] |
| | □□□ | | GR0,□□□ | ; GR0=VAL×4 |
| | □□□ | | GR0,□□□ | ; GR0=VAL×5 |
| | □□□ | | GR0,□□□ | ; GR0=VAL×10 |
|
[答え] |
| | SLA | | GR0,2 | ; GR0=VAL×4 |
| | ADDA | | GR0,VAL | ; GR0=VAL×5 |
| | SLA | | GR0,1 | ; GR0=VAL×10 |
|
結果が2の補数表現の正数の範囲なら、
「SLA」命令の代りに「SLL」命令でも可能です。
空欄を埋めるのではなければ、次の様なプログラムでも同じ結果になります。
SAMPLE | | START |
| | READ | | 0 |
| | SLA | | GR0,1 | ; GR0=DATA×2 |
| | ST | | GR0,VAL | ; VAL=DATA×2 |
| | SLA | | GR0,2 | ; GR0=VAL×4 |
| | ADDA | | GR0,VAL | ; GR0=VAL×5 |
| | WRITE | | 0 |
| | EXIT |
VAL | | DS | | 1 |
| | END |
|
一般的に、n倍するにはどうしたら良いでしょう。
先ほどの「10倍」は、シフトを使って計算しました。
同じ様に何倍するか分かっていれば、同様の方法が使えます。
例えば、17倍であれば次の様に出来ます。
これをプログラムに直すのは、簡単ですね。
何倍するかが分かっていない時にはどの様にすれば良いでしょうか?
その回数だけ加算を繰り返すなどいくつかの方法が考えられますが、
同じ処理をする命令を繰り返して書くのは大変です。
そこでその処理をする命令は1回しか書かないで、
その同じ命令を何度も繰り返して実行する必要があります。
次のプログラムは、加算と結果の表示を繰り返します。
尚、Rookでのアセンブル時に
「warn:命令の無いラベル行」というメッセージが出ますが、
これはRookでは問題ありません。
SAMPLE | | START |
| | READ | | 0 |
| | ST | | GR0,VAL | ; VAL |
| | LAD | | GR0,0 | ; SUM |
| | LAD | | GR1,0 | ; COUNT |
LOOP |
| | ADDA | | GR0,VAL | ; VAL×n |
| | LAD | | GR1,1,GR1 | ;COUNT UP |
| | WRITE | | 1 |
| | WRITE | | 0 |
| | JUMP | | LOOP |
VAL | | DS | | 1 |
| | END |
|
上記の様なラベルのみの行は、
Rookで拡張された表現であり、
厳密にはCASLの本来の文法では使えません。
本来の文法に従うなら、次の様にする必要があります。
LOOP | | ADDA | | GR0,VAL | ; VAL×n |
|
次の結果は、「5」を入力した場合の実行例です。
限りなく続くので、適当なところで中断してください。
(「Run」ボタンで連続実行する場合は、
「Stop」ボタンでの実行停止が必要になります。
「Stop」ボタンは、
連続実行中に「Run」ボタンの表示が「Stop」に変わったものです。)
Input : GR0 = 5(0005)
GR1=1(0001)
GR0=5(0005)
GR1=2(0002)
GR0=10(000A)
GR1=3(0003)
GR0=15(000F)
GR1=4(0004)
GR0=20(0014)
: : :
|
GR1が繰り返した回数、GR0がその数を入力した5に掛けた時の結果です。5の倍
数が順番に正しく表示されていますね。
新たに使用した命令は「JUMP」命令です。
コンピュータの中にはプログラム・レジスタという
特別のレジスタがあって、
「JUMP」命令は、
実効アドレスで指定したアドレスをこのプログラム・レジスタに入れます。
(CASLII以外では、「プログラム・カウンタ」「命令カウンタ」等と
呼ぶ場合もあります。)
プログラム・レジスタは、実行する命令のアドレスを指し示していて、
1命令の実行の度に通常は1命令分づつ増えてゆきます。
(レジスタ表示欄の「PR」と言う表示の位置に表示されますので、
確認してください。)
コンピュータはプログラム・レジスタが指し示すアドレスの命令を順次実行するので、
今までのプログラムでは命令を前から順に実行していました。
上の例では、「JUMP」命令を実行することで、
その次に実行する命令が「LOOP」ラベルの付いているアドレスの命令になります。
つまり、「JUMP」命令を使うことで
前に戻って同じ命令を繰り返し実行することが出来る訳です。
LOOP |
| | ADDA | | GR0,VAL | ; VAL×n |
|
この様にラベルは、データが記録されるアドレスを示す以外に、
命令の入っているアドレスを示すのにも使われます。
ということは、無理やり、
命令の入っているはずのアドレスにデータを入れることも可能です。
又、プログラム・レジスタが指すアドレスを、
命令ではなくデータの入っているアドレスにすることも可能です。
但し、命令ではないデータを命令として実行しようとして、
異常な動作をすることになります。
特別の意図がない限り、この様なことをしてはいけません。
Rookではこれを防止するため、
「Alart時、停止」の機能を有効にしておくことで、
この様な動作が行われようとした時には警告を出して停止します。
質問・ご意見等、お待ちしております。
小野智章(小野情報設計)
Mail to
Mail連絡先
©Copyright 1998-2001,2003-2005 小野智章(小野情報設計)
無断転載を禁止します。