このページではJavaScriptを使用しています。
Home > マイコン実用例 > 電子サイコロ > プログラム内容(その3)
プログラム内容(その3)

サイコロを2つ動かすプログラムです。アドレス8700からプログラムが始まっています。左側からアドレス、マシン語プログラム、アセンプラプログラムの順番で書かれています。
  プログラムは、ざっと次の動作をしています。

  • ディップスイッチでプログラムを分岐する。
  • スイッチ1,2を監視。それぞれのLEDに対応させます。
  • スイッチがONで乱数発生、サイコロ目のデータに変換して出力します。
  • もう1度ONでサイコロを乱数で回転させます。
  • 2つのサイコロが止まったときに、大きい数の方のLEDを点滅させます。

その2までの例でサブルーチンでHLレジスタを壊してしまうとき、呼ぶ側でレジスタの保護をしていましたが、このプログラムでは、呼ばれる側の使用レジスタをDEレジスタに変更しました。一般的に汎用のサブルーチンの場合、プログラムの入り口でPUSH・出口でPOPを使用してレジスタを保護します。

・プログラムの説明
                        ;**********************************************
                        ;        サイコロプログラム                   *
                        ;      		(その3)                    *
                        ;**********************************************
                        ;---------- ジャンプテーブル
   8400                 PRG0 	EQU 08400H	;入門編のプログラム開始番地
   8500                 PRG1 	EQU 08500H	;その1のプログラム開始番地
   8600                 PRG2 	EQU 08600H	;その2のプログラム開始番地
                        
                        ;---------- ワーキングテーブル
   E000                 RREGL 	EQU 0E000H	;RANDOM REG L
   E001                 RREGH	EQU 0E001H	;RANDOM REG H

   E010                 SW1FLG	EQU 0E010H	;スイッチ1が押されると1
   E011                 SK1STS	EQU 0E011H	;サイコロ1の状態 (回転→1,停止→0)
   E012                 SK1DAT	EQU 0E012H	;サイコロ1の数字データ
   E013                 SK1LED	EQU 0E013H	;サイコロ1のLEDデータ
   E014                 SK1PO	EQU 0E014H	;サイコロ1の出力ポート

   E020                 SW2FLG	EQU 0E020H	;スイッチ2
   E021                 SK2STS 	EQU 0E021H	;サイコロ2     〃
   E022                 SK2DAT	EQU 0E022H	;  〃
   E023                 SK2LED	EQU 0E023H	;  〃    〃
   E024                 SK2PO	EQU 0E024H	;  〃
                        ;---------- I/O テーブル
   0004                 PA 	EQU 04H		
   0005                 PB	EQU 05H		
   0006                 PC	EQU 06H		
   0007                 MODE	EQU 07H		
                                                
   8700                 	ORG 8700H	;プログラム開始アドレス
                        
   8700   3E 90         PINIT:	LD A,90H	;--- I/O ポートモードセット
   8702   D3 07         	OUT (MODE),A	;PA=IN,PB=OUT,PC=OUT
   8704   CD AC 87      	CALL INPTA	;PAポート入力
   8707   CB 42         	BIT 0,D		;データのBIT5を調べる
   8709   CA 00 84      	JP Z,PRG0	;ディップスイッチ1がONなら入門編へ
   870C   CB 4A         	BIT 1,D		;データのBIT4を調べる
   870E   CA 00 85      	JP Z,PRG1	; ディップスイッチ2がONならその1へ
   8711   CB 52         	BIT 2,D		;データのBIT3を調べる
   8713   CA 00 86      	JP Z,PRG2	;ディップスイッチ3がONならその2へ
                        	
   8716   3E 01         START:	LD A,1		;--- ワーキングテーブルイニシャライズ
   8718   32 11 E0      	LD (SK1STS),A	;回転ステータスをセット(ランダム点灯)
   871B   32 21 E0      	LD (SK2STS),A	;
   871E   3E 00         	LD A,0		;
   8720   32 10 E0      	LD (SW1FLG),A	;スイッチOFFをセット
   8723   32 20 E0      	LD (SW2FLG),A	;
   8726   3E 05         	LD A,PB		;出力ポートをメモリにセットしておく
   8728   32 14 E0      	LD (SK1PO),A	;
   872B   3E 06         	LD A,PC		;
   872D   32 24 E0      	LD (SK2PO),A	;
                        
                        ;========== サイコロ メイン ===========
                        
   8730   CD E5 87      MAIN:	CALL TIM	;チャタリング防止の待ち時間
   8733   CD AC 87      	CALL INPTA	;データをポートから入力
   8736   CB 72         	BIT 6,D		;データのBIT6を調べる
   8738   21 10 E0      	LD HL,SW1FLG	;  サイコロ1テーブルをセット
   873B   D5            	PUSH DE		;
   873C   28 02         	JR Z,SW1ON	;
   873E   36 01         	LD (HL),1	;1なら(スイッチ1が押されたら)SW1FLGを1にする
   8740   CC B6 87      SW1ON:	CALL Z,SKSTP	;0なら 停止サブルーチンへ
   8743   D1            SW2CHK:	POP DE	
   8744   CB 7A         	BIT 7,D		;入力データのBIT7を調べる
   8746   21 20 E0      	LD HL,SW2FLG	;  サイコロ1テーブルをセット
   8749   28 02         	JR Z,SW2ON	;
   874B   36 01         	LD (HL),1	;1なら(スイッチ2が押されたら)SW2FLGを1にする
   874D   CC B6 87      SW2ON:	CALL Z,SKSTP	;0なら 停止サブルーチンへ
                        
   8750   3A 11 E0      KORO:	LD A,(SK1STS)	;----サイコロ1のフラグチェック
   8753   FE 00         	CP 0
   8755   F5            	PUSH AF
   8756   CA 61 87      	JP Z,KORO2	;1→LEDランダム点灯,0→サイコロ2へ
   8759   CD EE 87      	CALL RDM	;乱数ルーチン(1~6)
   875C   CD D4 87      	CALL KOROME	;サイコロデータに変換
   875F   D3 05         	OUT (PB),A	;サイコロデータをポートBへOUT
   8761   F1            KORO2:	POP AF
   8762   3A 21 E0      	LD A,(SK2STS)	;----サイコロ2のフラグチェック
   8765   0F            	RRCA
   8766   D2 73 87      	JP NC,CHK	;1→LEDランダム点灯,0→MAINへ
   8769   CD EE 87      	CALL RDM	;乱数ルーチン(1~6)
   876C   CD D4 87      	CALL KOROME	;サイコロデータに変換
   876F   D3 06         	OUT (PC),A	;サイコロデータをポートCへOUT
   8771   18 BD         	JR MAIN
   8773   20 BB         CHK:	JR NZ,MAIN	;両方のサイコロが止まっているとき
   8775   ED 4B 12 E0   	LD BC,(SK1DAT)	;C←SK1DAT,B←SK1LED
   8779   2A 22 E0      	LD HL,(SK2DAT)	;L←SK2DAT,H←SK2LED
   877C   79            	LD A,C		;
   877D   BD            	CP L		;どちらが大きい数か比較
   877E   0E 0A         	LD C,10		;点滅カウンターを10にセット
   8780   38 04         	JR C,V2		;2の人の勝ち
   8782   06 00         	LD B,0		;
   8784   20 02         	JR NZ,V1	;引き分けは両方ブリンク
   8786   26 00         V2:	LD H,0		;
   8788   78            V1:	LD A,B		;ブリンク
   8789   D3 05         	OUT (PB),A	;
   878B   7C            	LD A,H
   878C   D3 06         	OUT (PC),A
   878E   CD E5 87      	CALL TIM
   8791   3A 13 E0      	LD A,(SK1LED)
   8794   D3 05         	OUT (PB),A
   8796   3A 23 E0      	LD A,(SK2LED)
   8799   D3 06         	OUT (PC),A
   879B   CD E5 87      	CALL TIM
   879E   0D            	DEC C
   879F   20 E7         	JR NZ,V1	;10回繰り返し
   87A1   3E 01         	LD A,1		;サイコロをまわす
   87A3   32 11 E0      	LD (SK1STS),A	;
   87A6   32 21 E0      	LD (SK2STS),A
   87A9   C3 30 87      	JP MAIN
                        
                        ;========== サブルーチン==========
   87AC   DB 04         INPTA:	IN A,(PA)	;ポートAのデータをAレジスタに読み込む
   87AE   57            	LD D,A
   87AF   DB 04         	IN A,(PA)	;正確なデータをとる為2度読みをする
   87B1   BA            	CP D		;最初に読み込んだデータと比較する
   87B2   C2 AC 87      	JP NZ,INPTA	;違っていたら再チェック
   87B5   C9            	RET
                        ;--------------------------------
                        ; スイッチONからOFFになったときサイコロ止める
   87B6   7E            SKSTP:	LD A,(HL)	;スイッチフラグ(SWFLG)を調べる
   87B7   FE 00         	CP 0		;
   87B9   C8            	RET Z		;0ならリターン(スイッチ押されてない)
   87BA   36 00         	LD (HL),0	;SWFLGをクリア
   87BC   23            	INC HL		;
   87BD   7E            	LD A,(HL)	;サイコロの状態フラグ(SKSTS)を調べる
   87BE   FE 00         	CP 0            ;
   87C0   36 01         	LD (HL),1	;0ならSKSTSを1 (回転)にしてリターン
   87C2   C8            	RET Z           ;
   87C3   36 00         	LD (HL),0	;1ならSKSTSを0にする
   87C5   23            	INC HL		;
   87C6   CD EE 87      	CALL RDM	;ランダムデータルーチン
   87C9   77            	LD (HL),A
   87CA   23            	INC HL
   87CB   CD D4 87      	CALL KOROME	;サイコロ変換ルーチン
   87CE   77            	LD (HL),A	;
   87CF   23            	INC HL
   87D0   4E            	LD C,(HL)	;
   87D1   ED 79         	OUT (C),A	;指定のポートに出力
   87D3   C9            	RET
                        
                        ;---------- データをサイコロに変換 ----------
                        ;数字をAにセットしてコールする
   87D4   11 DE 87      KOROME:	LD DE,SKTABL
   87D7   3D            LOOP:	DEC A
   87D8   13            	INC DE
   87D9   C2 D7 87      	JP NZ,LOOP
   87DC   1A            	LD A,(DE)
   87DD   C9            	RET
                        
   87DE                 SKTABL	;--サイコロデータ --
   87DE   00 08 41 49   	DB 00H,08H,41H,49H,55H,5DH,77H	 
   87E2   55 5D 77      
                        
                        ;---------- タイマールーチン ----------
   87E5   11 00 10      TIM:	LD DE,1000H
   87E8   1B            TLP:	DEC DE
   87E9   7A            	LD A,D
   87EA   B3            	OR E
   87EB   C8            	RET Z
   87EC   18 FA         	JR TLP
                        	
                        ;---------- 乱数 ----------
   87EE   CD 01 88      RDM:	CALL RDMGEN	;乱数発生ルーチン
   87F1   3A 01 E0      	LD A,(RREGH)
   87F4   E6 07         	AND 7		;下3ビットをとる	
   87F6   FE 07         	CP 7		;7,0をはねる
   87F8   CA EE 87      	JP Z,RDM
   87FB   FE 00         	CP 0
   87FD   CA EE 87      	JP Z,RDM
   8800   C9            	RET
                        
                        ;----------  RANDOM GENERATOR ----------
   8801   3A 01 E0      RDMGEN:	LD A,(RREGH)	;以下、乱数発生ルーチン
   8804   A7            	AND A		;(M系列)
   8805   28 1D         	JR Z,INITLD
   8807   57            	LD D,A
   8808   CB 07         	RLC A		;5ビット左シフト
   880A   CB 07         	RLC A
   880C   CB 07         	RLC A
   880E   CB 07         	RLC A
   8810   CB 07         	RLC A
   8812   AA            	XOR D		;ビット2と7のXORをとる
   8813   E6 80         	AND 80H		;
   8815   F5            	PUSH AF
   8816   3A 00 E0      	LD A,(RREGL)	;
   8819   17            	RLA		;ビット7→キャリーへ
   881A   7A            	LD A,D
   881B   17            	RLA		;データシフト キャリー→ビット0
   881C   32 01 E0      	LD (RREGH),A
   881F   F1            	POP AF
   8820   32 00 E0      	LD (RREGL),A	;次の入力をビット7に保存
   8823   C9            	RET
   8824   3E FF         INITLD:	LD A,0FFH
   8826   32 01 E0      	LD (RREGH),A
   8829   18 D6         	JR RDMGEN
   882B                 	END