実数計算はできるけど、計算結果の表示はできない?

SDCCにはfloat型(しかもIEEE形式)の実数演算機能が備わっています。doubleはさすがにありません。

#include <stdarg.h>
#include <stdio.h>

void (*wexit)() = (void *)0x0083 ;
void (*conout)(char) = (void *)0x008c ;

int putchar(int c)
{
	if (c == '\n')
		conout('\r') ;
	conout(c) ;
	return c ;
}

void main()
{
	int i ;
        float x = 0.123 ;

	for (i = 0; i < 10; i++) {
		printf("i = %d, %f\n", i, x*i) ;
	}
	wexit() ;	// プログラムの終了
}

float1.c

喜び勇んで上記のような確認用のプログラムの作成してコンパイルし、Z80-COREで実行してみました。

あれ?コンパイルはできたのに<NO FLOAT>って何?って感じです。

float1.cの実行結果

確認してみると、printf()関数の書式指定に%fの処理が組み込まれていないことがわかりました。

なんと大胆な。計算できても表示できないんじゃ、計算できているかどうかもわかりませんよね。

本当に計算できているの?

そこで、計算が本当に正しく行われているのか、計算結果を1000倍して整数にキャストして表示するプログラムに変更して動作確認をしてみました。

今度はメイン関数だけを提示。

void main()
{
	int i ;
        float x = 0.123 ;

	for (i = 0; i < 10; i++) {
		printf("i = %d, %d\n", i, (int)(x*i*1000)) ;
	}
	wexit() ;	// プログラムの終了
}

float2.c

整数に変換された結果なので、今度は表示されています。

また、計算結果も問題ないようです。(ワンパターンないい加減な計算だけど)

float2.cの実行結果

計算結果の表示ができないけれど、実数計算ができることが確認できました。

動作確認したのは掛け算だけなので、四則演算の確認をしておきましょう。

void main()
{
	int i ;
        float x = 0.123 ;

	for (i = 0; i < 10; i++) {
		printf("i = %d, %d, %d, %d, %d\n",
                        i, (int)(x*i*1000), (int)(x/i*1000),
                        (int)(x+i*1000), (int)(x-i*1000)) ;
	}
	
	wexit() ;	// プログラムの終了
}

float3.c

ちゃんと動作しているようですが、加減算に関しては、まったく不完全な確認例でしたね。すみません。

float3.cの実行結果

実数計算プログラムのコードサイズ

float3.cは評価用の簡単なプログラムですが、コンパイルコードは7Kバイト程度のコードサイズになっています。8K BASICのコード容量に迫る勢いです。

float3.cのコンパイルで作成されたMAPファイルの内容を確認して見ましょう。

_CODEという名前のエリア(セグメント)を取り上げてみます。

表の左端のValueの欄は、その右の関数が配置されているアドレスです。

このアドレスの値と次の行の値との差がその関数のコードサイズを示しています。最大の関数は__print_formatで、2.5K程度を占有していることがわかります。__printf_formatは、printfの表示形式の処理を行う関数ですので、printf関数を使用しようとすると、__printf_formatを含めて、それだけで3Kバイト程度のコード領域を占めてしまうことがわかります。現在は組み込まれていない%fへの対応コードを追加すると、さらにコード量は増大します。なんにせよ、何気なくprintfを使うと、それだけで、TinyBasicが十分動くメモリを消費してしまうということですね。

Area                                    Addr        Size        Decimal Bytes (Attributes)
--------------------------------        ----        ----        ------- ----- ------------
_CODE                               00004020    00000F4A =        3914. bytes (REL,CON)

      Value  Global                              Global Defined In Module
      -----  --------------------------------   ------------------------
     00004020  _putchar                           float3
     0000403C  _main                              float3
     00004140  _exit                              crt0
     00004146  ___sdcc_call_hl                    
     0000414D  _vprintf                           vprintf
     00004159  _printf                            vprintf
     00004417  ___mulsint2slong                   u_16_16_mul
     00004445  ___muluint2ulong                   u_16_16_mul
     0000453A  __print_format                     printf_large
     00004F5E  _strlen                            

つぎに、_HOMEという名前のエリア(セグメント)を取り上げてみます。

ここには、実数演算で使用する関数群が配置されています。四則演算処理が、それぞれ_fsxxxという関数名で実現されているように見えます。関数名の中に2があるのはtoの短縮形で、それぞれ、データの型変換用の関数の様です。これらの合計バイト数は2775バイトと表示されています。

これを見ると、実数演算を行うプログラムには、その処理用の関数群として、まずは3Kバイト程度が追加されると考える必要があります。

Area                                    Addr        Size        Decimal Bytes (Attributes)
--------------------------------        ----        ----        ------- ----- ------------
_HOME                               00004F6E    00000AD7 =        2775. bytes (REL,CON)

      Value  Global                              Global Defined In Module
      -----  --------------------------------   ------------------------
     00004F6E  ___fssub                           _fssub
     00004F96  ___fsmul                           _fsmul
     00005253  ___fsadd                           _fsadd
     0000567C  ___sint2fs                         _sint2fs
     00005684  ___fs2sint                         _fs2sint
     000056B8  ___fsdiv                           _fsdiv
     00005767  ___fs2slong                        _fs2slong
     0000579C  ___slong2fs                        _slong2fs
     000057BB  ___ulong2fs                        _ulong2fs
     00005866  ___fs2ulong                        _fs2ulong
     00005947  ___fslt                            _fslt

計算結果の表示を行わない実数計算プリケーション

ちょっと困った状態ではありますが、マンデルブロ集合表示プログラムは、実数計算はするけれども、その計算結果の数値を直接表示しないので、現状のSDCCの応用先にぴったりです。

ということで、別の記事にあらためて、SDCCによるマンデルブロ集合表示プログラムの実行に関するレポートを報告します。