Z80

擬似乱数を実装

2012年7月31日

0から32767までの擬似乱数を発生する関数、RND()を実装した。

2012-07-31-rnd.png

はじめ、stdlib.hにあるrand()関数を使用しようとしたが、スタティック変数の初期化部分が現在のSDCCを使用したMZ-80用のプログラミングにあわないため、自分で書くことにした。よく使われる32ビット整数に定数を掛けて定数を足すやり方で実装しようとしたところ、32ビット演算用のCのライブラリの大きさなのだかの理由で、2kbの大きさになってしまった。コードがこんなに大きくては使えない。色々調べた結果、Microchip社のMathユーティリティ(AN544)に載っている方法を採用することになった。該当部分のコードは、以下のとおり。

void getRand(){
	__asm
		LD HL,(#_g_seed)
		LD B,#15
		
	loop:
		LD A,H
		RLA    // bit 14 of HL will be in bit 7 of A
		XOR H  // XOR of bits 15 and 14 of HL will be in bit 7 of A
		RLA    // XOR of bits 15 and 14 of HL will be in carry bit
		RLA    // XOR of bits 15 and 14 of HL will be in bit 0 of A
		LD D,A // Store XOR value in D register
		LD A,H // bit 12 of HL will be in bit 4 of A
		RRA    // bit 12 of HL will be in bit 3 of A
		XOR L  // XOR of bits 12 and 3 of HL will be in bit 3 of A
		RRA    // XOR of bits 12 and 3 of HL will be in bit 2 of A
		RRA    // XOR of bits 12 and 3 of HL will be in bit 1 of A
		RRA    // XOR of bits 12 and 3 of HL will be in bit 0 of A
		XOR D
		AND #0x01
		ADD HL,HL
		OR L
		LD L,A
		DJNZ loop
		
		LD (#_g_seed),HL
		LD A,H
		AND #0x7F
		LD D,A
		LD E,L
	__endasm;
}

ビット15, 14, 12, 3のXORを取り、それをビット0に入れるような方法で左シフトする。この変換を1回行っただけだと、発生する乱数が前の乱数の2倍に近いような値に偏るため、15回演算した後に下位15ビット(0-32767)を返すようにしてある。

コメント

コメントはありません

コメント送信