TMPZ84C015上のモニターでSDCCによるc言語でprintfを実行してみました。

以前作成しているモニターではTMPZ84C015のシリアルの初期化を行っているので、まずはprintf文に必要なputchar()を作成してみます。

使用したSDCCは下記のバージョンのものです。

$ sudo apt-get install sdcc

$ sdcc -v
SDCC : mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/TININative/ds400/hc08/s08/stm8 3.8.0 #10562 (Linux)
published under GNU General Public License (GPL)

SDCCでは、main文を呼び出すための初期化と後始末を行うcrt0.sがありますが、今回の仕様になるように変更しました。

変更点は、スタックは設定せず、モニターに任せます。

帰りは、retでモニターに戻ります。

変更したcrt0.sは次の通りです。 mycrt0.asmで保存します。

	.module crt0
	.globl	_main


	;; Ordering of segments for the linker.

	.area	_CODE


	.area	_DATA


	.area   _CODE
init::

	call	_main
	ret


	.area	_DATA

作成したmycrt0.asmをアセンブルします。

$ asz80 -l -s -o mycrt0.asm

cのコンパイルには作成された mycrt0.relを使用します。

次にputcharを作成します。

putcharの本体は、モニターでも使用している一文字出力ルーチンです。

mainルーチンから呼ばれると、まず、引数をスタックにセットし、続いてputcharからの戻りアドレスをスタックに積みます。

putcharのルーチン内は、引数を取り出すために、戻りアドレスを+2したスタック値で引数を取得します。
返り値は、HLをクリアしています。
putchar.asmで保存します。

;;   int putchar(uint8_t)
;;
_putchar::
	ld	hl,	#0002
	add	hl,	sp
putchar01:
	in	a,	(0x1b)
	bit	2,	a
	jr	z,	putchar01
	ld	a,	(hl)
	out	(0x1a),	a
	ld	hl,	#0000
	ret

アセンブルします。

$ asz80 -l -s -o putchar.asm

putcharを使用した例題を作成ます。

mainでputchar()を呼び出し、”J”を表示します。
putchar_main.cで保存します。

#include	<stdint.h>

extern	uint8_t	 putchar(uint8_t);

int main(void)
{
	putchar(0x4a);
	return(0);
}

コンパイルします。
先ほど作成したmycrt0.relとputchar.relが必要になります。

$ sdcc -mz80 --out-fmt-ihx --code-loc 0xa000 --no-std-crt0 -o putchar_main.ihx mycrt0.rel putchar_main.c putchar.rel
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA

作成されたputchar_main.ihxをモニターで読み込み実行してみました。

>c a000 y:
J
>

putcharが正常に動くようですので、purintfを実行してみます。

下記の例題を用意します。
printf_main.cで保存します。

#include	<stdio.h>

int main(void)
{
	printf("Hello SDCC Z80 C world\n");
	return(0);
}

コンパイルします。
先ほど作成したmycrt0.relとputchar.relが必要になります。

$ sdcc -mz80 --out-fmt-ihx --code-loc 0xa000 --no-std-crt0 -o printf_main.ihx mycrt0.rel printf_main.c putchar.rel
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA

作成されたprintf_main.ihxをモニターで読み込み実行してみました。

>c a000 y:
Hello SDCC Z80 C world

>

printf上で算術演算を行ってみます。
この場合には算術演算等の処理のために容量がすごく多くなります。
printf_purasu.cで保存します。

#include	<stdio.h>

int main(void)
{
	printf("10 + 25=%d\n",10 + 25);
	return(0);
}

コンパイルします。
先ほど作成したmycrt0.relとputchar.relが必要になります。

$ sdcc -mz80 --out-fmt-ihx --code-loc 0xa000 --no-std-crt0 -o printf_purasu.ihx mycrt0.rel printf_purasu.c putchar.rel
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA

作成されたprintf_purasu.ihxをモニターで読み込み実行してみました 。

>c a000 y:
10 + 25=35
>

SDCCで色々できそうなので、Cプログラムに挑戦していきたいと思います。

おすすめの記事