標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第586回]
●整数BASICコンパイラ(SBASIC)についてもう少しくわしく
本日も朝からずっとND80ZVの取扱説明書の作成作業をしておりました。
説明を書いておりますと、
いや、これはまずいなあ、
というところが出て来たりして、するとプログラムの変更作業とか、プログラムリストの見直しとかをしなくてはいけないことになって、なかなか時間がかかります。
整数BASICコンパイラ(SBASIC)について、もう少し別のプログラムでも説明をしたいと思っているのですが、本日はそんなわけで、プログラムを走らせてみたり、写真などを準備したりする時間がありませんでした。
ですから、今回は先回お見せしましたSBASICコンパイラで作成された機械語(マシン語)のプログラムをネタにしまして、どうしてこういうプログラムが生成されるのか、といったあたりを、説明することにいたします。
前回お見せしました、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
このソースプログラムをSBASICコンパイラでコンパイルして、機械語のプログラムファイルsbtest2.binが作られたのですが、どのような機械語のプログラムが生成されたかを確認するために、sbtest2.binをZ80逆アセンブラ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
ソースプログラムは短いものでしたが、コンパイルの結果作成された機械語のプログラムはかなり長いものになってしまいました。
どうしてこんなに長くなってしまうのだろう、と疑問に思われたかもしれません。
このあたりがコンパイラの欠点といいますか弱点なのです。
これがCコンパイラなどになりますと、ほんの数行のソースプログラムなのに、コンパイルすると、数十Kバイトものプログラムファイルが生成されたりします。
アセンブラですと、プログラマが人間の頭で考えて、その場合の目的に合ったプログラミングをしますから、短くて効率のよいプログラムになります。
ところがコンパイラの場合には、ソースプログラムが汎用的な性格をもった言語、命令で組み立てられるために、どうしても汎用的な翻訳の仕方をすることになってしまいます。
もちろんコンパイラも、ソースプログラムを細かく場合分けをして、最適な機械語プログラムに変換するように工夫することによって、短くて効率のよい機械語プログラムに変換することもできるようになりますが、そうしようとすればするだけ、コンパイラ自体のサイズが大きくなって重たいものになってしまいます。
このSBASICコンパイラは、そのような効率を追求するために作ったものではありませんから、それほど能率のよい変換はできないのです。
Z80BASICインタプリタでは遅すぎて困るが、かといって、Z80アセンブラでプログラムを書くのはちょっとつらい、という場合に簡単に利用できる、ということを目的に作ったものですから、多少非能率なところがあっても、その目的には十分かなったものだと思います。
さて、そこで、どこがどうなると、このように長くなってしまうのか、ということの説明です。
上の逆アセンブルリストと、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