2016.8.21
前へ

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

[プチ連載です]
Legacy8080用オプションボードの製作

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
葛Z術少年出版様からLegacy8080用のオプションボード製作の依頼を受けました。
そのボードには電流制限素子(ポリスイッチ)をつけることになりました。
そこで…。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜


[第23回]


●OUT命令、IN関数のテスト(2)

前回からの続きです。
前回は最も簡単なOUT命令のプログラムと、その内容を一部変更することで少しですが実行時間を短縮できるプログラムを紹介しました。

さて、次のプログラムは前回変更したプログラムにさらに少し変更を加えたプログラムです。
このプログラムの実行結果はどうでしょうか?

    10 'out test3
    20 OUT $E3,$80
    30 A%=0,B%=1,C%=$E0
    40 OUT C%,A%:OUT C%,B%
    50 GOTO 40


40行のOUT文がマルチステートメントになっています。
下が実行結果です。

前回の変更後のプログラムは、1回のHLの出力にかかる時間が0.44msほどに短縮されました。
それが今回はさらにわずかですが0.42msほどに短縮されました。

1行ずつ実行するときに、次の行に移る過程でいろいろな作業を行なっていて、そのためにわずかですが時間がかかってしまいます。
マルチステートメントの場合には1行の中ですぐ次の命令を読み込む操作にかかるため余計な時間はかかりません。
それが前回のプログラムと今回とのわずかな実行時間の差になります。

次にIN関数についてもテストをしてみました。
今度は少し複雑なテストです。
下はテスト中の写真です。

Bポートのビット0をAポートのビット0に接続しています。
下はテストプログラムです。

    10 'out in test
    20 OUT $E3,$82
    30 OUT $E0,0
    40 B%=IN($E1)
    50 OUT $E2,B%
    60 OUT $E0,1
    70 B%=IN($E1)
    80 OUT $E2,B%
    90 GOTO 30


20行でBポートのみを入力に設定します。
前回のテストと同じようにAポートから0、1を出力しますが、今度は出力した直後にBポートの値をIN関数で読み込み、それをCポートから出力します。

出力波形の写真です。

上側(CH1)がAポートからの出力で、下側(CH2)がCポートからの出力です。
上の写真は、30行のOUT $E0,0が実行されてCH1がLになったあと、40行のIN関数が実行され、そのあと50行でOUT $E2,B%が実行されてCH2がLになったことを示しています。
CH1がLになってからCH2がLになるまでの時間は約0.5msです。
前回の最初のテストでOUT命令の実行時間は0.2msでした。
ということはIN関数の実行時間は0.3msということになります。
CH2がLになったあとCH1がHになるのに0.2msかかっています。
これは60行のOUT文の実行結果です。
そのあとCH2がHになるまでに0.5msかかっています。
これは70行と80行の実行結果です。
そのあとCH1がLになるまで0.4msほどかかっています。
ここはちょっと注意が必要なところです。
90行のGOTO文と30行のOUT文の実行結果ですから前回の最初のテストの結果から考えるとここは0.3msのはずなのですが。
実はこのプログラムではGOTO文の実行時間は0.2msだと考えられます。
GOTO文は現在のメモリ上の位置から前に、または後ろに順に行番号をサーチしていくように作られています。
90行のGOTO文の行き先は30行ですから現在位置よりも前にサーチしていきます。
前回の最初のプログラムのGOTO文は50行にありました。
間には40行の1行があるだけです。
今回は間に40、50、60、70、80と5行のプログラムがあります。
その行番号を80行から逆にサーチしていって30行に行き着くまでには前回のプログラムよりも多くの時間を必要とします。
そのため今回のGOTO文を実行するのには0.2msかかるという結果になったのです。

なぜBASICインタプリタはそんな効率の悪い、面倒な仕組みになっているのかといいますと、それはインタプリタの特徴に関わっています。
コンパイラはソースプログラムを機械語に毎回翻訳しなければなりません。
ということはたとえば間にプログラムを追加したり削除したり変更したりしても、かならずコンパイルという作業をしますから、ソースプログラムの変更については何も考える必要はありません。
それだけむしろコンパイラのほうがシンプルな構造にできるともいえます。
これに対してインタプリタはソースプログラムの状態のままで(実は行入力時にただちに中間言語に翻訳しているのですが)すぐに実行が可能です。
またもとのプログラムに新たな行を追加したり削除したりしても、やはりすぐに実行できます。
また前回見ていただいたように、メモリの中では中間プログラムとでもいうような構造になっているのですが、それを/SAVEコマンドでファイルとしてセーブすると、中間コードから普通のテキスト文を生成してテキストファイルとして保存できます。
それらの機能をもたせるために、インタプリタは複雑な構造が必要になるのです。
もちろん工夫によってもっと速く実行できるような構造にすることもできますが、そうするためにはBASICインタプリタ本体のプログラムサイズがより大きなものになってしまいますし、その開発にはより多くの時間を必要とします。
決して現在の機能に満足しているわけではありませんが、プログラムの改良はなかなか大変なことなので、とりあえずは現在の仕様となっています。

なお前回と今回見ていただいたZB3BASICのOUT命令、IN関数の実行時間は葛Z術少年出版のLegacy8080での実行結果です。
ND80Z3.5(ND80ZV)のZB3BASICでも同じプログラムでテストできますが(ただしその場合にはI/OアドレスをE0〜E3から80〜83に変更する必要があります)、Legacy8080のCPUクロックが10MHzであるのに対してND80Z3.5(ND80ZV)は6MHzなので、ここで説明した実行時間よりも遅くなります。

ということでZB3BASICのOUT命令とIN関数の実行時間について見ていただきましたが、最後に参考までに同じことをマシン語プログラムで実行してみます。

前回の最初のプログラムと全く同じ動作をするマシン語プログラムを即席でアドレス9000〜に書いてすぐに実行しました。

このように短いプログラムはマシン語コードをそのままCMコマンドで書き込むのが一番手っ取り早い方法です。
ここで書き込んだプログラムをアセンブラのプログラムリストとして表記すると下のようになります。

9000 3e80        LD A,80
9002 d3e3        OUT (E3),A
9004 3e00   LOOP:LD A,00
9006 d3e0        OUT (E0),A
9008 3e01        LD A,01
900A d3e0        OUT (E0),A
900C c30490      JP LOOP


実行結果です。

H出力が3μs、L出力は2μsです。
このことからLDとOUTの実行時間の合計は2μs、JPは1μsであることが分かります。
マシン語プログラムはBASICインタプリタの100倍高速であるということがいえるでしょう。

前回、今回と連載を延長しましたが、今回で当プチ連載は終了です。

Legacy8080用オプションボードの製作[第23回]
2016.8.21upload

前へ

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