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