優:ど、どうもこんにちは……柊優です……。10回目を迎えるけど、やっぱりこういうのは慣れないね……。今回もよろしく……。
陽香:永乃原陽香です。今月も、よろしくお願いしますね。
愛梨:結城愛梨です。今回もよろしくねー。ねぇねぇ、二人とも。今回は何するの?
はい。今回は、スーパーバイザコールとNOP命令、そしてCASL2で乗除算のやり方について学んでいきますよ。
おー、今日はなんか盛りだくさんだー。大変だけど、がんばらなくっちゃ!
それでは、さっそくはじめていこうか……。
【 OSにお願いするスーパーバイザコール命令 】
それではさっそく、スーパーバイザコール(SVC)の命令からだ。これは、指定されたアドレスのプログラムの使用許可をOSに求める、というものだよ。
???
実は、入出力処理やハードウェア制御はOSが担当する処理で、プログラマが作ったプログラムでは行うことはできないんですよ。
そこで、OSに依頼して、そのプログラムを使わせてもらうというのが、スーパーバイザコールだよ。
え? でも、ボクたちは、IN命令やOUT命令で入出力ができてるよ?
実はそれにもSVCが絡んでいるんだ。IN命令やOUT命令は、関数やサブルーチンに似てると言ったよね? つまり、入出力を行うための処理をまとめたものなんだけど、その処理の中にSVCが含まれてるんだ……。
それで、IN命令やOUT命令で入出力ができた、というカラクリですね。なお、CASL2でのSVCは、このようにマクロ命令の中で使われるのが主で、実際に私たちが使うことはありませんよ。
なるほどー。
念のために、SVC命令の書き方を教えておこうか。SVCのオペコードはそのままSVCで、このように書くんだ。
SVC [アドレス]
SVC [アドレス],[レジスタ]
上の書き方だと、[アドレス]番地にあるプログラムの使用許可をOSに出しなさい、という意味になり、下だと、[レジスタ]の内容に[アドレス]を足した結果の番地にあるプログラムの~、という意味になるよ。
はーい、わかったよっ。
それでは次は、NOP命令について学んでいきましょう。
【 何もしないのがNOP命令なんだ 】
次はNOP命令だ。NOPはNon OPeration。つまり、何もしない命令なんだ。何もしないことを、明示的に示す命令なんだ。書き方はただNOP。これだけでOKさ。
ええっ!? そんな何もしない命令を書いて、何になるの?
確かにイメージしづらいですよね。でも、CASL2のプログラミングを練習していけば、わかるようになりますよ。
うーん……。なんか複雑というか。
それでは次はいよいよ、CASL2で乗除算をする方法について学んでいこう。
【 掛け算割り算には工夫が必要なのです 】
ねぇねぇ、掛け算、割り算とはいうけど、ここまで学んできた中にはそんな命令はなかったよ? 隠してるんだったら早く教えてよー。
ふふふ。その通り、CASL2には乗除算をする命令は本当にありませんよ。そこで、工夫をしてその処理を作っていくわけです。
ここでは、そのアプローチについて簡単にレクチャーしていくよ。まずはアプローチその1、ループを使う方法だ。
ループを?
うん。小学校で掛け算を習ったときのことを思い出してほしいんだけど、掛け算は[掛けられる数]を[掛ける数]だけ足すことみたいなことを習わなかったかな?
あ、そういえば。
例えば、3×4は特別な計算ではなく、3を4つ(あるいは4回)足すというのが基本的な意味というわけですね。ということは……?
あ、そうか! つまりループを使って、掛けられる数を、掛ける数だけ足すという処理を作ればいいわけか!
その通りだよ。具体的な流れは下の通りだけど、やっていることは同じ。掛けられる数を足し合わせる処理を、ループで掛ける数の回数だけやっているわけさ。
ちなみに、割り算もこれと逆のアプローチでできますよ。[割られる数]から[割る数]を引いていき、[割られる数]が[割る数]より小さくなった時、この引いた回数が割り算の答え(商)、この時点での[割られる数]の残りが余りとなるんです。
では、アプローチその2だ。その2は、再帰処理を使う方法さ。
再帰処理?
再帰処理とは、あるサブルーチンから、その自分自身を呼ぶ方法です。原理はループを使う方法と同じ。ただ、ループを再起処理に置き換えているだけです。
なるほどー……。
そして三つ目はシフト命令を使う方法だ。
シフト命令を? どう使うの?
これの原理を説明するのは難しいから説明は省くんだけど、流れは次の通りだよ。なお、ここでは掛けられる数を数A、掛ける数を数Bとするね。
(1) 数Bの一番右のビット(最下位ビット)をチェックする
(2) 1であれば、答え用のレジスタに数Aを足し合わせる
(3) 数Aを左に1ビット論理シフト、数Bを右に1ビット論理シフトさせる
(4) 数Bが0でなければ、(1)に戻る
(5) 数Bが0なら、それで掛け算終了。その時点での答え用のレジスタの値が積(掛け算の答え)となる。
ネットで調べれば、このロジックをプログラムにしたものが見つかるから調べてみてね。
う、うん、わかった。ちんぷんかんぷんだけど……。
割り算も、シフト命令を使ってできますよ。こちらの考え方は若干人間寄りかもしれません。
(1) 割る数(数Bとする)に、どれだけの数を掛ければ割られる数(数A)と同じか近い数になるか考える。(これを数Cとする)
(2) 数Aから(数B×数C)を引いたものが余りとなる
(3) この余りが数Bより小さければ、割り算は終了。割り算の答え(商)と余りが導き出される。余り>=数Bであれば(1)に。
この(1)の過程には、シフト命令を使われることが多いようです。左シフトさせれば2倍になりますからね。
このアルゴリズムの考え方はプログラマー各人によって違うから、これが正解!というプログラムはないんだ。自分でアルゴリズムを考えるのも手かもしれないよ。
うん、わかったよ。
それでは今回はここまで。次回はいよいよ最終回。実際に練習問題を解いていく予定だよ。いよいよラストだ、頑張っていこうね。
はーいっ。
それでは、また次回、お会いいたしましよう。
※次の更新は、レトロゲーレビューの予定です。お楽しみに!