標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第585回]
●整数BASICコンパイラ(SBASIC)の続きです
今回も前回に続いてSBASICについてのお話です。
前回はI/Oポートにパルスを出力する簡単なプログラムを、機械語(マシン語)、Z80BASICインタプリタ、そしてSBASICコンパイラでそれぞれ作って、実行した結果をオシロスコープで見てみました。
一番短い幅のパルスを出力する、といった意味合いのプログラムでしたから、それはそれなりに意味のあるプログラムですけれど、余りに簡単すぎました。
とにかくOUT文とGOTO文しかありませんから、これではBASICのありがたみもちょっと実感できそうにありません。
そこで今回はもう少し、といっても本当に少しだけなのですが、長いプログラムを作って、前回と同じようにオシロスコープで見て比較してみたいと思います。
前回と同じように、まずはZ80BASICです。
10 OUT $83,$80 20 A%=100 30 B%=0 40 OUT $80,0 50 B%=B%+1:IF B%<=A% GOTO 50 60 B%=0 70 OUT $80,1 80 B%=B%+1:IF B%<=A% GOTO 80 90 GOTO 30
今回はパルスに幅を持たせました。
最初はB%=0からスタートして、1ずつ加算して、B%=100になるまで、100回加算を繰り返します。
B%=100になったら82C55のAポートのビット0出力を反転し、またB%=0からスタートして、B%=100になるまで、100回加算を繰り返します。
B%=100になったら、また82C55のAポートのビット0出力を反転し、これを繰り返します。
プログラムの実行結果です。
出力がH、Lの間にそれぞれ加算(B%=B%+1)と比較(IF)とGOTO文を100回繰り返しています。その実行時間は約130msecです。
今度は機械語(マシン語)のプログラムです。
前回は16進数の命令コードをダイレクトに入力しましたが、今回は数値の比較を行うところがありますから、Z80アセンブラを使うことにしました。
アセンブラのソースプログラムです。
メモ帳(notepad)で書きました。
;ASMTEST2 10.8.17 ORG $8050 VAP=$F440 VBP=$F442 ; LD A,80 OUT (83),A LOOP0:OUT (80),A LD DE,(VBP) LOOP1:LD HL,(VAP) OR A INC DE SBC HL,DE JP NZ,LOOP1 INC A JP LOOP0
今回のプログラムは、Z80BASICのサブルーチンとして書きました。
もっとも、この機械語プログラムの中でずっとループし続けますから、BASICプログラムにはリターンしませんけれど。
BASICのメインプログラムからA%の値とB%の値をもらいます。
Z80BASICは整数型の変数A%〜Z%、文字型の変数A$〜H$を固定したメモリエリアに置いています。
A%はF440、B%はF442にあります。
A%〜Z%、A$〜H$のアドレスはいつも同じアドレスになっていますから、それらの変数の値を、BASICプログラムから機械語のサブルーチンに渡したり、その逆に機械語サブルーチンで処理した結果を、それらの変数エリアに書き込むことで、結果をBASICのメインプログラムに渡すことができます。
プログラムはDEレジスタの値を+1(インクリメント)して、その結果をHLレジスタの値と比較しています。
Z80には16ビットの数を比較する命令はありませんから、DEとHLとの比較を行うのに、減算命令SBC HL,DEを利用しています。
その前にあるOR AはSBC HL,DEでキャーリーを引いてしまわないようにするために、キャリーをクリアする目的で使っています。
Z80アセンブラ(ZASM.COM)でアセンブルして機械語(マシン語)のバイナリファイルを作成します。
Z80BASICを起動して、バイナリファイルをロードします。
NEWコマンドはBASICプログラムを格納する開始アドレスを指定するコマンドです。
Z80BASICが起動した直後は、BASICプログラムの格納開始アドレスは8004になります。
今回は機械語のプログラムを8050から実行開始するように書きましたから、そのプログラムのロードするエリアを確保するために、NEW,8100を実行しています。
BASICのメインプログラムはA%とB%の値を定義して、機械語サブルーチンコール命令USR()を実行するだけのプログラムです。
USR()命令の()の中には機械語サブルーチンのエントリアドレス(スタートするアドレス)を指定します。
実行結果です。
100回の加算(インクリメント)と比較(減算)とジャンプ命令の実行時間は0.8msecほどです。
そして、次はSBASICです。
'SBASIC TEST2 10/8/17 ORG=$8004 OUT $83,$80 *LOOP:B%=0 OUT $80,0 *LOOP1:B%=B%+1:IF B%<=A% GOTO *LOOP1 B%=0 OUT $80,1 *LOOP2:B%=B%+1:IF B%<=A% GOTO *LOOP2 GOTO *LOOP
BASICインタプリタのプログラムとほとんど同じです。
SBASICコンパイラで機械語のバイナリファイルを作成します。
前回と同じように、コンパイルの結果作成されたバイナリファイルsbtest2.binを逆アセンブラZDAS.COMで逆アセンブルしてみました。
逆アセンブルしてできたリストです。
8004 218300 LD HL,$0083 8007 4D LD C,L 8008 218000 LD HL,$0080 800B ED69 OUT (C),L 800D 210000 LD HL,$0000 8010 2242F4 LD ($F442),HL 8013 218000 LD HL,$0080 8016 4D LD C,L 8017 210000 LD HL,$0000 801A ED69 OUT (C),L 801C 2A42F4 LD HL,($F442) 801F E5 PUSH HL 8020 210100 LD HL,$0001 8023 D1 POP DE 8024 CD643E CALL $3E64 8027 2242F4 LD ($F442),HL 802A 2A42F4 LD HL,($F442) 802D E5 PUSH HL 802E 2A40F4 LD HL,($F440) 8031 D1 POP DE 8032 B7 OR A 8033 ED52 SBC HL,DE 8035 CB7C BIT 7,H 8037 210100 LD HL,$0001 803A 2803 JR Z,03 803C 2D DEC L 803D 1802 JR 02 803F 7D LD A,L 8040 B7 OR A 8041 C21C80 JP NZ,$801C 8044 210000 LD HL,$0000 8047 2242F4 LD ($F442),HL 804A 218000 LD HL,$0080 804D 4D LD C,L 804E 210100 LD HL,$0001 8051 ED69 OUT (C),L 8053 2A42F4 LD HL,($F442) 8056 E5 PUSH HL 8057 210100 LD HL,$0001 805A D1 POP DE 805B CD643E CALL $3E64 805E 2242F4 LD ($F442),HL 8061 2A42F4 LD HL,($F442) 8064 E5 PUSH HL 8065 2A40F4 LD HL,($F440) 8068 D1 POP DE 8069 B7 OR A 806A ED52 SBC HL,DE 806C CB7C BIT 7,H 806E 210100 LD HL,$0001 8071 2803 JR Z,03 8073 2D DEC L 8074 1802 JR 02 8076 7D LD A,L 8077 B7 OR A 8078 C25380 JP NZ,$8053 807B C30D80 JP $800D 807E C9 RET
ソースプログラムは短いものでしたが、コンパイルの結果作成された機械語のプログラムはこんなに長いものになりました。
SBASICコンパイラでバイナリファイルとともに作成されたsbtest2.wkファイルです。
0000 'SBASIC TEST2 10/8/17 0000 ORG=$8004 8004 OUT $83,$80 800D *LOOP:800D B%=0 8013 OUT $80,0 801C *LOOP1:801C B%=B%+1:802A IF B%<=A% GOTO *LOOP1 8044 B%=0 804A OUT $80,1 8053 *LOOP2:8053 B%=B%+1:8061 IF B%<=A% GOTO *LOOP2 807B GOTO *LOOP 807E
SBASICコンパイラで作成された、機械語のバイナリファイルは、Z80BASICを起動してから、/LDコマンドでメモリにロードします。
さきほどの機械語サブルーチンと同様に今回コンパイルの結果作成された機械語のプログラムもBASICプログラムのサブルーチンとして実行します。
機械語サブルーチンは通常のBASICプログラムが開始される8004にロードされましたが、さきほどの機械語サブルーチンのテストのときに、BASICプログラムは8100から作成して、それがそのまま残っていますから、今回の機械語プログラムを8004からロードしても、BASICプログラムは破壊されずにちゃんと残っています。
実行した結果です。
最初のBASICインタプリタのプログラムと同じように、100回の加算と比較とGOTOが実行されていますが、4.4msecほどです。
アセンブラで作成した機械語のプログラムは0.8msecでしたから、それよりは遅いのですけれど、インタプリタのプログラムは130msecでしたから、それと比較すれば、桁違いに速い、ということが言えます。
2010.8.17upload
前へ
次へ
ホームページトップへ戻る