先日basic で動かしたマンデルブロー集合の描画でbasic が遅い、ということを痛感して、もう少し速く動かしたときどの程度差があるのかな、ということで、アセンブラでロジックを記述して動かそうと思いました。
問題は、このプログラム、浮動小数点演算を使っているので、ライブラリが必要ということ。で、最初はbasic の中の浮動小数点演算ルーチンを使わせてもらうことを考えていたのですが、まずもって、アセンブラで記述したプログラムをpokeなどでメモリに転送してusr関数で実行するということをやってくれるbasic のプログラムを作成するのが面倒です。
それでだんだん当初の趣旨から外れて、浮動小数点ライブラリを簡単に使えるプログラミングスタイルについてしらべてました。Z80のアセンブラもいろいろあり、cp/m で動作するもの、windows, linuxなどで動作するもの、Web(online)で動作するもの、いろいろありますが、アセンブラはニモニックはともかくも、疑似命令や、引数の計算ルールが様々で、なかなかまとまって、どこかから持ってきた演算ライブラリを引いて、すっきり実行できるものがありません。なかなか悩ましいところです。
それで、Cコンパイラも視野に調べたのですが、こちらも、cp/m で動作するBDS-Cがなかなか、と思いましたがこちらは浮動小数点がサポートされておらず、結局hi-tech-cぐらいでしょうか?Arduino的に簡単にソースコードを書いてZ80で何かするのに一番いいのは。
そんなことを調べて時間をずいぶんつぶしてしまいました。
現在のところ、CP/M program EXEcutor for Win32 を使い、hi-tech c を動かし、下記のソースをコンパイル、.com ファイルを前に作ったZ80-MBCがすでにCP/M Ver 2.2が動いているのでそちらのvirtual disk に.com ファイルを書き込んで動作させる、ということはできました。
Cのソースは、下記のような、もともとのBASICのプログラムそのまま、みたいな感じですが、浮動小数点ライブラリをリンクしてコンパイルしました。
#include <stdio.h>
#include <math.h>
main ()
{
float ca,cb;
int i;
int y,x;
float t,a,b;
for (y=-12;y<=12;y++) {
for (x=-39;x<=39;x++) {
ca=x*0.0458;
cb=y*0.08333;
a=ca;
b=cb;
for (i=0;i<=15;i++) {
t=a*a-b*b+ca;
b=2.0*a*b+cb;
a=t;
if (a*a+b*b>4.0) goto l200;
}
printf(" ");
goto l210;
l200:
if (i>9) i=i+7;
printf("%c",48+i);
l210:
continue;
}
printf("\n");
}
}
Z80-MBCで実行してみたところ、82秒ほどで絵を作成できました。CPUは4MHz でこれは動いているので、同じ条件で比較はできていませんが、1桁はいかないけど、ぐらい高速になる、と考えてよいかな。
これがまあまあ、調子よいので、SBCZ80の方も、CP/MのシリアルI/Oを実装してCP/Mのバイナリを動かすのが楽にいろいろできる方法かな、と思っているところです。
コンパイルしたバイナリーをPCでCP/M program executor で動かすと、最初はちょっと時間(1秒ぐらい?)かかるんですが、2回目からは、どこかのキャッシュが働くのか一瞬で結果が出ます。どういう仕組みが背景にあるのかななどちょっと興味深く思いました。
assembler やhi-tech-cでコンパイルしたバイナリ(COMファイル)をCP/Mに転送するのに毎回virtual disk を作ってたら日が暮れてしまうので、シリアルで転送する方法を試行錯誤していました。
xmodem がいいのではということで、いろいろと試していたんですが、うまくいっておらず、今のところ、.com をpython bin2hex.py –offset=0x100 hoge.COM > hoge.HEXのようにhexに変換し、pip hoge.HEX=con: でcp/m のディスクに保存し、 load hoge.HEXでcp/m のディスクにCOMファイルを作成するような確実だけど回りくどい方法を取っています。xmodemが上手くいかないのは、タイミングがPC側とあってないのかも。