2022.7.22
前へ
次へ
ホームページトップへ戻る


PIC−USBIO using BASIC

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
USBインターフェースを内蔵したPICを使ってWindowsパソコンで外部回路を制御するための各種I/O基板の製作記事です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

[第26回]



●ダイレクトモード

私がBASICインタプリタにこだわっている大きな理由のひとつにダイレクトモードがあります。
ダイレクトモードはレガシーなBASICインタプリタではごく普通に備わっている機能です。
しかしBASICコンパイラに限らずコンパイラ言語でダイレクトモードがあるというものを私は寡聞にして知りません。
工夫すれば可能かもしれませんが多分BASICコンパイラにダイレクトモード機能を付加するのは難しいと思います。
ダイレクトモードにこだわるならばやはりコンパイラではなくてインタプリタだということになります。

ダイレクトモードはキーボードから入力した1行の命令文をただちに実行する機能です。
当初PIC−USBIO用BASICインタプリタをTEXT型で作成した時点ではもちろんごく普通にダイレクトモードの機能付きで作りました([第11回]参照)。
そこに書いてありますようにキーボードから行番号付きの命令文を入力すると、それはプログラムの一部としてメモリに蓄えられます。
その一方で行番号をつけない命令文を入力するとダイレクトモードと解釈されて直ちに実行されます。
この機能を構築するのはTEXT型のBASICインタプリタではそれほど難しいことではありません。
しかし中間言語型では少し事情が異なってきます。
中間言語型のBASICインタプリタではTEXT型のソースプログラムを中間言語型のプログラムに変換してから実行します。
そこのところをダイレクトモードではどうクリアするのか。
これはちょっと悩ましい問題です。
実はND80Z3.5などのZB3BASICインタプリタも中間言語型です。
ZB3BASICインタプリタはND80Z3.5などのCPUボード上の限られた容量のRAMにプログラムを格納しなければなりません。
そのためにかなり面倒な作業をこなしています。
逆にZB3BASICの場合にはBASICはUSB接続の状態で使うという条件によって、システム的にはダイレクトモードと通常のモードとの区別をそれほど意識する必要がありません。
行番号付きのプログラムをキーボードから入力する場合でも、行番号なしでダイレクトモードとして入力する場合でも、あるいは/LOADコマンドによってファイルからロードする場合でも、USBを介してWindowsパソコンからマイコンボードに読み込まれるという点では全て同じです。
ZB3BASICではUSB経由で送られてきた時点で一行ごとにTEXTから中間言語に翻訳しています。

PIC−USBIO用BASICインタプリタでもそれと同じやり方を踏襲することもできないことではありません。
しかしWindowsパソコンの場合にはメモリの制約はそれほど気にする必要はありませんから、ZB3BASICとは別の考え方をすることも可能です。
ということで中間言語型のPIC−USBIO用BASICインタプリタでは/LOAD後かまたはRUNの直前にプログラムを一括して中間言語型に翻訳することにしました。
勿論その時点でダイレクトモードをどうするかについても考える必要があるということは認識していました。
それについてはいずれ作業が進んだ時点で考えましょう、ということでここまできたのでした。
とりあえず作業も大体のところはめどが立ちましたのでいよいよダイレクトモードに取り掛かりました。
あれこれ考えてみたのですが、結局一番よい方法はキーボードから行番号なしの命令文が入力されたときに、その1行を中間言語に翻訳してそのまま直ちに実行するという方法でした。
結果としてそのようにシステムを作ったのですが。
そうすると、ダイレクトモードのために1行を中間言語型に翻訳するという方法をそのまま拡大すれば、行番号付きで入力された1行もそのまま直ちに中間言語に翻訳するということもできますし、また/LOADでファイルから読み込まれるプログラムも1行読み込む毎に翻訳することもできることになります。

しかし問題はちょっと複雑なのです。
そのようにすると、それでは翻訳後にプログラムの一部を書き換えたらどうするか、とか一部の行を追加または削除した場合にはどうするのかということへの対処が難しくなります。
ダイレクトモードでは入力されるのは1行の命令文だけなのでそのような問題は出てきません。
中間言語型のBASICインタプリタを作ることにはそういった困難な点があります。
それがわかっているので、最初はTEXT型のBASICインタプリタでいくつもりでした。
でももう走り出してしまいましたから今更後戻りはできません。
これから工夫してなんとかうまい着地点を見つけるつもりです。

前置きが長くなってしまいました。
ともかくとりあえず作った中間言語型BASICインタプリタでのダイレクトモードの実例です。
まずはダイレクトモードについての理解を助けるために普通の簡単なプログラムを実行します。

見ての通りの簡単なプログラムです。
上のように実行したあとでダイレクトモードを使ってみます。

a=10:goto *abc
と入力するとこの文には行番号がありませんから直ちに実行されます。
その結果は上の画面の最後の行のように表示されました。
aが10になりcが466になっています。

ダイレクトモードはただ単に入力する1行が実行されるだけにとどまらず上の例のように現在メモリ上にあって実行可能なプログラムにエントリすることなども可能なのです。
ここがダイレクトモードの大きな特徴でこれはインタプリタだからこそできることで、このような機能をコンパイラで実現することは困難であると考えています。
すでに実行済みのプログラムやダイレクトに実行した命令文の実行結果をそのまま受けて続けてダイレクトモードで新しい命令文を実行することも可能です。

先ほどの結果に続けてさらに
c=b/a:print a,b,c
を入力しました。
この文も直ちに実行されてその結果c=45になりました。
ダイレクトモードはこのように「直ちに実行される」という即時性が大きな特徴です。
これは実に便利な機能で、時には非常に大きな武器になることもあります。
たとえばすでに実行したプログラムがかなり大きなプログラムで、たまたま実行した結果が納得できなかったような場合、その途中で使われたはずの変数の値などを知りたいと思ってもプログラムでその値をPRINTするようにはしてなかったならば通常はそれを確認することはできません。
しかしもしも欲しいと思う変数の値がプログラムの終了時まで書き換わっていなければ、その値をPRINTするようにはプログラムしてなかったとしても、ダイレクトモードでPRINT文を実行することでその値を確認することができます。
簡単な例で説明します。

プログラムを実行した結果z=669になりました。
ここで途中の値xとyも表示しておくべきだったと気が付いたとします。
もちろん上のプログラム例ならばPRINT文を追加したうえで再実行すれば済むことです。
しかし本当は長いプログラムでしかもプログラムの一部を書き換えて再実行したのでは結果が変わってしまうという再現が難しいケースだったと考えてください。
そのようなときにダイレクトモードが威力を発揮します。
下のようにダイレクトモードでPRINT文を実行すればよいのです。

このようにとても便利な使い方ができるダイレクトモードが備わっていることを覚えておくと思わぬ助けになることがきっと出てくると思います。
あわててプログラムを書き換えたりする前にまずはダイレクトモードでなんとかできないか考えてみてください。

ダイレクトモードは現在メモリに存在するプログラムそのものに影響を与えたりはしません。
またあえてプログラムの実行結果が格納されている変数の値などを書き換えたりしない限り変数の値などもそれ以前の実行結果のまま残ります。
下はそのことを示す例です。

プログラムを実行したあとでダイレクトモードで全く別の命令文を実行しました。
このようにFOR〜NEXT文などもマルチステートメント記述でダイレクトに実行することができます。
そのあとでLISTコマンドを実行してみました。
プログラムはもとのまま残っています。
ソースプログラムだけではなくてそれを翻訳した中間言語プログラムももとのまま残っていますから、上の例の場合には(先にすでに中間言語型への翻訳も終っていますから)そのままRUNコマンドを入力して実行することができます。

今までの説明では先に通常のプログラムを中間言語に翻訳してそれを実行したあとでダイレクトモードを実行しました。
しかし先に通常のプログラムをロードして実行したあとでなければダイレクトモードは使えないということではありません。
PIC−USBIO用BASICインタプリタを起動した直後でも普通にダイレクトモードを使うことができます。

起動直後なのでプログラムは何もロードされていませんし1行も入力されていません。
念のためそのことをLISTコマンドで確かめてみました。
そのあとでダイレクトモードで
for a=0 to 10:print a,;:next a:print
と入力しました。
そのあとでもう一度確認のためLISTコマンドを実行しました。
ダイレクトモードは通常のプログラムの作成モードとは異なっているのでLIST表示には出てきません。
ダイレクトモードで入力したプログラム行はそのときだけのものであとには残りません(スクリーンエディタを利用してカーソルをダイレクト入力した行に移動してそこで[Enter]を押せば再実行することができます)。
ダイレクトモードで実行した結果の値はそのまま残ります。
そのことをダイレクトモードでprint aを実行して確認してみました。
先のFOR〜NEXT文でa=0〜a=10まで繰り返し実行してa=11でループを抜け出しましたから残っているaの値は11です。
そのようにダイレクトモードはいきなり実行することができます。
プログラムを作成していく過程でちょっと1行入力してその命令文でよいかどうかを試してみるというような都合の良い使い方が簡単にできてしまいます。
ダイレクトモードはとても便利な機能なのです。

PIC−USBIO using BASIC[第26回]
2022.7.22upload

前へ
次へ
ホームページトップへ戻る