FizzBuzz(FORTH、Z80アセンブラ)

どうしてプログラマに・・・プログラムが書けないのか?に出てくるアレをFORTHで書いてみた。pForthとかで動く。

101 1 DO i . i 3 MOD 0 = IF ." Fizz" THEN i 5 MOD 0 = IF ." Buzz" THEN LOOP

せっかくなのでZ80アセンブラでも書いてみようと思ったが、公倍数かどうか求めるための割り算や余りを求める命令が無いので、まずはD÷E=DあまりAの処理を書いてみる。翌日続きを書いてマス。

DIV:	LD	B,8
	XOR	A
LOOP:	CP	A,E
	JR	C,SKIP
	SUB	A,E
SKIP:	CCF
	RL	D
	RL	A
	DJNZ	LOOP
	RET

後で使いやすいように、ちょっと改変。A÷B=AあまりBにする。DEも保存。Z80ニモニック風だと DIV A,B ってな具合か。

DIV:	PUSH	DE
	LD	D,A
	LD	E,B
	LD	B,8
	XOR	A
LOOP:	CP	A,E
	JR	C,SKIP
	SUB	A,E
SKIP:	CCF
	RL	D
	RL	A
	DJNZ	LOOP
	LD	B,A
	LD	A,D
	POP	DE
	RET

Aの内容をHLが示す場所から10進文字列で格納する処理を書いてみる。8ビットの数値だと、10進数で3桁しかないのでループにはしてない。

DEC:	LD	B,100
	CALL	DIV
	ADD	A,'0'
	LD	(HL),A
	INC	HL
	LD	A,B
	LD	B,10
	CALL	DIV
	ADD	A,'0'
	LD	(HL),A
	INC	HL
	LD	A,B
	ADD	A,'0'
	LD	(HL),A
	RET	

上記の例だと5が005で出ちゃうんで、ゼロサプレス処理を追加する。ついでにHL以外の全レジスタ保存。HLは格納した次のアドレスを差す。Z80ニモニック風だと DEC (HL),A ってな具合か。

DEC:	PUSH	AX
	PUSH	BC
	PUSH	DE
	LD	B,100
	CALL	DIV
	LD	C,A
	CP	0
	JR	Z,SKIP1
	ADD	A,'0'
	LD	(HL),A
	INC	HL
SKIP1:	LD	A,B
	LD	B,10
	CALL	DIV
	CP	0
	JR	NZ,SKIP2
	LD	A,C
	CP	0
	JR	Z,SKIP3
SKIP2:	ADD	A,'0'
	LD	(HL),A
	INC	HL
SKIP3:	LD	A,B
	ADD	A,'0'
	LD	(HL),A
	INC	HL
	POP	DE
	POP	BC
	POP	AF
	RET	

やっとこさ、例のアレを書いてみる。画面出力はCP/MMSX-DOSを意識して末尾を"$"にした文字列をBUFから始まるアドレスに書き出している。

ARE:	LD	A,1
	LD	HL,BUF
LOOPA:	LD	(HL),' '
	INC	HL
	CALL	DEC
	PUSH	AX
	LD	B,3
	CALL	DIV
	POP	AX
	LD	A,B
	CP	0
	JR	NZ,SKIPA
	LD	(HL),'F'
	INC	HL
	LD	(HL),'i'
	INC	HL
	LD	(HL),'z'
	INC	HL
	LD	(HL),'z'
	INC	HL
SKIPA:	PUSH	AX
	LD	B,5
	CALL	DIV
	POP	AX
	LD	A,B
	CP	0
	JR	NZ,SKIPB
	LD	(HL),'B'
	INC	HL
	LD	(HL),'u'
	INC	HL
	LD	(HL),'z'
	INC	HL
	LD	(HL),'z'
	INC	HL
SKIPB:	INC	A
	CP	100
	JR	C,LOOPA
	LD	(HL),'$'
	RET

定時後、いつもの下道で帰宅。昨日から始めた親のThinkPad T20の再セットアップの続き。途中、晩御飯にオムライスとスープ。ThinkPad T20はHDDからカコン、カコンと音がしたり、内蔵光学ドライブが読み込み不良起こしたり、Windows XPインストール時の再起動で動かなくなるなど調子が悪い。
内蔵光学ドライブの読み込み不良はウルトラベイ2000のある箇所の底面にネジが1本余分に付いていたのが原因。はずしたらウルトラベイ2000の取り付け、取り外しも出来るようになった。なんで、こんなネジが付いて(いつの間に付けた)んだ??
何はともあれ、HDD不良や再起動不調も収まって何とかインストール完了。明日はアプリケーションのインストールをしよう。