2026.8.21
前へ
次へ
ホームページトップへ戻る


[新連載開始]W65C02マイコンボードの製作

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
私としてはW65C02をさわるのは全く初めてです。何から何まで未経験です。さてどうなりますでしょうか。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

[第50回]



●AND,ORA,EOR(2)テストプログラム●謎解きです

ANDのテストプログラムです。
下がアセンブラソースプログラムです。
;w65c02test22 26/8/10
;
;and
;
        org $8000
;
;set data
        ldx #$fd;stack pointer
        txs
        ldx #$10
        ldy #$20
        lda #$12
        sta $1000;1000<12,,,a
        lda #$34
        sta $1000,x;1010<34,,,a,x
        lda #$56
        sta $1000,y;1020<56,,,a,y
        lda #$78
        sta $10;10<78,,,zp
        lda #$10
        sta $10,x;20<10,,,(zp,x)
        sta $11,x;21<10,,,1010
        sta $23;23<10,,,(zp)
        lda #$20
        sta $22;22<20,,,1020
        ;$00,x,,,10<78 zp,x
        ;zp=10,(zp)=1010,(zp),y=1030
        lda #$9a
        sta $1030
;
;start
        tsx;stack pointer to x
        stx $30
;
        lda #$0f
        ldx #$10
        ldy #$20
;
        and $1000;12>02
        pha;02
        lda #$0f
        and $1000,x;34>04
        pha;04
        lda #$0f
        and $1000,y;56>06
        pha;06
        lda #$0f
        and #$bc;bc>0c
        pha;0c
        lda #$0f
        and $10;78>08
        pha;08
        lda #$0f
        and ($10,x);20,21,,,1010<34 34>04
        pha;04
        lda #$0f
        and ($22);22,23,,,1020<56,,,(zp) 56>06
        pha;06
        lda #$0f
        and $00,x;,,,10<78,,,zp,x 78>08
        pha;08
        lda #$0f
        and ($20),y;($20)=1010,y=20,,,1030<9a 9a>0a
        pha;0a
        tsx;stack pointer to x
        stx $31;
        stp
;end
W65C02アセンブラでアセンブルしました。

下はアセンブルした結果作成されたアセンブルリストです。
0000        ;w65c02test22 26/8/10
0000        ;
0000        ;and
0000        ;
8000            org $8000
8000        ;
8000        ;set data
8000 A2FD       ldx #$fd;stack pointer
8002 9A         txs
8003 A210       ldx #$10
8005 A020       ldy #$20
8007 A912       lda #$12
8009 8D0010     sta $1000;1000<12,,,a
800C A934       lda #$34
800E 9D0010     sta $1000,x;1010<34,,,a,x
8011 A956       lda #$56
8013 990010     sta $1000,y;1020<56,,,a,y
8016 A978       lda #$78
8018 8510       sta $10;10<78,,,zp
801A A910       lda #$10
801C 9510       sta $10,x;20<10,,,(zp,x)
801E 9511       sta $11,x;21<10,,,1010
8020 8523       sta $23;23<10,,,(zp)
8022 A920       lda #$20
8024 8522       sta $22;22<20,,,1020
8026            ;$00,x,,,10<78 zp,x
8026            ;zp=10,(zp)=1010,(zp),y=1030
8026 A99A       lda #$9a
8028 8D3010     sta $1030
802B        ;
802B        ;start
802B BA         tsx;stack pointer to x
802C 8630       stx $30
802E        ;
802E A90F       lda #$0f
8030 A210       ldx #$10
8032 A020       ldy #$20
8034        ;
8034 2D0010     and $1000;12>02
8037 48         pha;02
8038 A90F       lda #$0f
803A 3D0010     and $1000,x;34>04
803D 48         pha;04
803E A90F       lda #$0f
8040 390010     and $1000,y;56>06
8043 48         pha;06
8044 A90F       lda #$0f
8046 29BC       and #$bc;bc>0c
8048 48         pha;0c
8049 A90F       lda #$0f
804B 2510       and $10;78>08
804D 48         pha;08
804E A90F       lda #$0f
8050 2110       and ($10,x);20,21,,,1010<34 34>04
8052 48         pha;04
8053 A90F       lda #$0f
8055 3222       and ($22);22,23,,,1020<56,,,(zp) 56>06
8057 48         pha;06
8058 A90F       lda #$0f
805A 3500       and $00,x;,,,10<78,,,zp,x 78>08
805C 48         pha;08
805D A90F       lda #$0f
805F 3120       and ($20),y;($20)=1010,y=20,,,1030<9a 9a>0a
8061 48         pha;0a
8062 BA         tsx;stack pointer to x
8063 8631       stx $31;
8065 DB         stp
8066        ;end
ANDの動作確認をアドレッシングモードを変えながら行なうために適当な初期値をセットしメモリアドレスにもセットしてプログラムを開始します。
アキュムレータに#$0Fを入れて各アドレッシングモードで事前にストアしておいた値とのANDを計算してその結果をスタックにプッシュします。
計算後の値は全部上位4ビットが0になり下位4ビットのみが計算前の値になります。
ちょっとイージーなプログラムです。
手抜きしています。
このプログラムはW65C02のスタックポインタ(SP)は初期設定をしなければならないらしいということに気が付いた後に書いたものなのでSPの初期設定をしています。
とはいえまだよくわかっていなかったところもあってSPにFDなどという半端な値を設定しています。
1)$1000の値12と0FとのANDを計算した結果の値02をスタックにプッシュします。
2)$1000,xの値34と0FとのANDを計算した結果の値04をスタックにプッシュします。
xは10ですから$1000,xは$1010になります。
3)$1000,yの値56と0FとのANDを計算した結果の値06をスタックにプッシュします。
yは20ですから$1000,yは$1020になります。
4)即値#$BCと0FとのANDを計算した結果の値0Cをスタックにプッシュします。
5)$10の値78と0FとのANDを計算した結果の値08をスタックにプッシュします。
6)($10,x)の値34と0FとのANDを計算した結果の値04をスタックにプッシュします。
($10,x)は間接アドレッシングです。
xは10ですから$10,xは$20になります。
$20、$21の値は10、10ですから$1010の値がターゲットの値になります。
7)($22)の値56と0FとのANDを計算した結果の値06をスタックにプッシュします。
($22)も間接アドレッシングです。
$22、$23の値は20、10ですから$1020の値がターゲットの値になります。
8)$00,xの値78と0FとのANDを計算した結果の値08をスタックにプッシュします。
xは10ですから$00,xは$10になります。
9)($20),yの値9Aと0FとのANDを計算した結果の値0Aをスタックにプッシュします。
($20)は間接アドレッシングです。
$20、$21の値は10、10ですから$1010をyで修飾したものがターゲットのアドレスになります。
yは20ですからターゲットのアドレスは$1030になります。
$1030の値は9Aです。
プログラムを開始したときのSPの値を$30にストアします。
プログラムを開始したときのSPの値はFDです。
プログラムを実行すると$01FDから前に向かって順に
02,04,06,0C,08,04,06,08,0A
がストアされSPの値はF4になります。
実行後のSPの値を$31にストアします。

65c02test22.binをロードして実行しました。

実行後にSPの値を確認しました。
$30がFD、$31がF4になっています。

スタックの中身を確認しました。

/DM 01でスタックの値を確認しました。
上に書いた通りアドレス$01FDから前に向かって
02,04,06,0C,08,04,06,08,0A
になっています。

ORAのテストプログラムです。
下がアセンブラソースプログラムです。
;w65c02test23 26/8/10
;
;ora
;
        org $8000
;
        ldx #$fd;stack pointer
        txs
;set data
        ldx #$10
        ldy #$20
        lda #$12
        sta $1000;1000<12,,,a
        lda #$34
        sta $1000,x;1010<34,,,a,x
        lda #$56
        sta $1000,y;1020<56,,,a,y
        lda #$78
        sta $10;10<78,,,zp
        lda #$10
        sta $10,x;20<10,,,(zp,x)
        sta $11,x;21<10,,,1010
        sta $23;23<10,,,(zp)
        lda #$20
        sta $22;22<20,,,1020
        ;$00,x,,,10<78 zp,x
        ;zp=10,(zp)=1010,(zp),y=1030
        lda #$9a
        sta $1030
;
;start
        tsx;stack pointer to x
        stx $30
;
        lda #$f0
        ldx #$10
        ldy #$20
;
        ora $1000;12>f2
        pha;f2
        lda #$f0
        ora $1000,x;34>f4
        pha;f4
        lda #$f0
        ora $1000,y;56>f6
        pha;f6
        lda #$f0
        ora #$bc;bc>fc
        pha;fc
        lda #$f0
        ora $10;78>f8
        pha;f8
        lda #$f0
        ora ($10,x);20,21,,,1010<34 34>f4
        pha;f4
        lda #$f0
        ora ($22);22,23,,,1020<56,,,(zp) 56>f6
        pha;f6
        lda #$f0
        ora $00,x;,,,10<78,,,zp,x 78>f8
        pha;f8
        lda #$f0
        ora ($20),y;($20)=1010,y=20,,,1030<9a 9a>fa
        pha;fa
        tsx;stack pointer to x
        stx $31;
        stp
;end
W65C02アセンブラでアセンブルしました。

下はアセンブルした結果作成されたアセンブルリストです。
0000        ;w65c02test23 26/8/10
0000        ;
0000        ;ora
0000        ;
8000            org $8000
8000        ;
8000 A2FD       ldx #$fd;stack pointer
8002 9A         txs
8003        ;set data
8003 A210       ldx #$10
8005 A020       ldy #$20
8007 A912       lda #$12
8009 8D0010     sta $1000;1000<12,,,a
800C A934       lda #$34
800E 9D0010     sta $1000,x;1010<34,,,a,x
8011 A956       lda #$56
8013 990010     sta $1000,y;1020<56,,,a,y
8016 A978       lda #$78
8018 8510       sta $10;10<78,,,zp
801A A910       lda #$10
801C 9510       sta $10,x;20<10,,,(zp,x)
801E 9511       sta $11,x;21<10,,,1010
8020 8523       sta $23;23<10,,,(zp)
8022 A920       lda #$20
8024 8522       sta $22;22<20,,,1020
8026            ;$00,x,,,10<78 zp,x
8026            ;zp=10,(zp)=1010,(zp),y=1030
8026 A99A       lda #$9a
8028 8D3010     sta $1030
802B        ;
802B        ;start
802B BA         tsx;stack pointer to x
802C 8630       stx $30
802E        ;
802E A9F0       lda #$f0
8030 A210       ldx #$10
8032 A020       ldy #$20
8034        ;
8034 0D0010     ora $1000;12>f2
8037 48         pha;f2
8038 A9F0       lda #$f0
803A 1D0010     ora $1000,x;34>f4
803D 48         pha;f4
803E A9F0       lda #$f0
8040 190010     ora $1000,y;56>f6
8043 48         pha;f6
8044 A9F0       lda #$f0
8046 09BC       ora #$bc;bc>fc
8048 48         pha;fc
8049 A9F0       lda #$f0
804B 0510       ora $10;78>f8
804D 48         pha;f8
804E A9F0       lda #$f0
8050 0110       ora ($10,x);20,21,,,1010<34 34>f4
8052 48         pha;f4
8053 A9F0       lda #$f0
8055 1222       ora ($22);22,23,,,1020<56,,,(zp) 56>f6
8057 48         pha;f6
8058 A9F0       lda #$f0
805A 1500       ora $00,x;,,,10<78,,,zp,x 78>f8
805C 48         pha;f8
805D A9F0       lda #$f0
805F 1120       ora ($20),y;($20)=1010,y=20,,,1030<9a 9a>fa
8061 48         pha;fa
8062 BA         tsx;stack pointer to x
8063 8631       stx $31;
8065 DB         stp
8066        ;end
プログラムはANDのプログラム65c02test22のANDをORAに変更し0FとのANDを計算するところをF0とのORを計算するように変更しただけで最初の値数やアドレスなどは変えていません。
プログラムを開始したときのSPの値を$30にストアします。
プログラムを開始したときのSPの値はFDです。
プログラムを実行すると$01FDから前に向かって順に
F2,F4,F6,FC,F8,F4,F6,F8,FA
がストアされSPの値はF4になります。
実行後のSPの値を$31にストアします。

65c02test23.binをロードして実行しました。

実行後にSPの値を確認しました。
$30がFD、$31がF4になっています。

スタックの中身を確認しました。

/DM 01でスタックの値を確認しました。
上に書いた通りアドレス$01FDから前に向かって
F2,F4,F6,FC,F8,F4,F6,F8,FA
になっています。

EORのテストプログラムです。
下がアセンブラソースプログラムです。
;w65c02test24 26/8/10
;
;eor
;
        org $8000
;
        ldx #$fd;stack pointer
        txs
;set data
        ldx #$10
        ldy #$20
        lda #$12
        sta $1000;1000<12,,,a
        lda #$34
        sta $1000,x;1010<34,,,a,x
        lda #$56
        sta $1000,y;1020<56,,,a,y
        lda #$78
        sta $10;10<78,,,zp
        lda #$10
        sta $10,x;20<10,,,(zp,x)
        sta $11,x;21<10,,,1010
        sta $23;23<10,,,(zp)
        lda #$20
        sta $22;22<20,,,1020
        ;$00,x,,,10<78 zp,x
        ;zp=10,(zp)=1010,(zp),y=1030
        lda #$9a
        sta $1030
;
;start
        tsx;stack pointer to x
        stx $30
;
        lda #$ff
        ldx #$10
        ldy #$20
;
        eor $1000;12>ed
        pha;ed
        lda #$ff
        eor $1000,x;34>cb
        pha;cb
        lda #$ff
        eor $1000,y;56>a9
        pha;a9
        lda #$ff
        eor #$bc;bc>43
        pha;43
        lda #$ff
        eor $10;78>87
        pha;87
        lda #$ff
        eor ($10,x);20,21,,,1010<34 34>cb
        pha;cb
        lda #$ff
        eor ($22);22,23,,,1020<56,,,(zp) 56>a9
        pha;a9
        lda #$ff
        eor $00,x;,,,10<78,,,zp,x 78>87
        pha;87
        lda #$ff
        eor ($20),y;($20)=1010,y=20,,,1030<9a 9a>65
        pha;65
        tsx;stack pointer to x
        stx $31;
        stp
;end
W65C02アセンブラでアセンブルしました。

下はアセンブルした結果作成されたアセンブルリストです。
0000        ;w65c02test24 26/8/10
0000        ;
0000        ;eor
0000        ;
8000            org $8000
8000        ;
8000 A2FD       ldx #$fd;stack pointer
8002 9A         txs
8003        ;set data
8003 A210       ldx #$10
8005 A020       ldy #$20
8007 A912       lda #$12
8009 8D0010     sta $1000;1000<12,,,a
800C A934       lda #$34
800E 9D0010     sta $1000,x;1010<34,,,a,x
8011 A956       lda #$56
8013 990010     sta $1000,y;1020<56,,,a,y
8016 A978       lda #$78
8018 8510       sta $10;10<78,,,zp
801A A910       lda #$10
801C 9510       sta $10,x;20<10,,,(zp,x)
801E 9511       sta $11,x;21<10,,,1010
8020 8523       sta $23;23<10,,,(zp)
8022 A920       lda #$20
8024 8522       sta $22;22<20,,,1020
8026            ;$00,x,,,10<78 zp,x
8026            ;zp=10,(zp)=1010,(zp),y=1030
8026 A99A       lda #$9a
8028 8D3010     sta $1030
802B        ;
802B        ;start
802B BA         tsx;stack pointer to x
802C 8630       stx $30
802E        ;
802E A9FF       lda #$ff
8030 A210       ldx #$10
8032 A020       ldy #$20
8034        ;
8034 4D0010     eor $1000;12>ed
8037 48         pha;ed
8038 A9FF       lda #$ff
803A 5D0010     eor $1000,x;34>cb
803D 48         pha;cb
803E A9FF       lda #$ff
8040 590010     eor $1000,y;56>a9
8043 48         pha;a9
8044 A9FF       lda #$ff
8046 49BC       eor #$bc;bc>43
8048 48         pha;43
8049 A9FF       lda #$ff
804B 4510       eor $10;78>87
804D 48         pha;87
804E A9FF       lda #$ff
8050 4110       eor ($10,x);20,21,,,1010<34 34>cb
8052 48         pha;cb
8053 A9FF       lda #$ff
8055 5222       eor ($22);22,23,,,1020<56,,,(zp) 56>a9
8057 48         pha;a9
8058 A9FF       lda #$ff
805A 5500       eor $00,x;,,,10<78,,,zp,x 78>87
805C 48         pha;87
805D A9FF       lda #$ff
805F 5120       eor ($20),y;($20)=1010,y=20,,,1030<9a 9a>65
8061 48         pha;65
8062 BA         tsx;stack pointer to x
8063 8631       stx $31;
8065 DB         stp
8066        ;end
プログラムはANDのプログラム65c02test22のANDをEORに変更し0FとのANDを計算するところをFFとのXORを計算するように変更しただけで最初の値数やアドレスなどは変えていません。
プログラムを開始したときのSPの値を$30にストアします。
プログラムを開始したときのSPの値はFDです。
プログラムを実行すると$01FDから前に向かって順に
ED,CB,A9,43,87,CB,A9,87,65
がストアされSPの値はF4になります。
実行後のSPの値を$31にストアします。

65c02test24.binをロードして実行しました。

実行後にSPの値を確認しました。
$30がFD、$31がF4になっています。

スタックの中身を確認しました。

/DM 01でスタックの値を確認しました。
上に書いた通りアドレス$01FDから前に向かって
ED,CB,A9,43,87,CB,A9,87,65
になっています。

●謎解きです

何をやっているかお分かりになりましたでしょうか。
もう一度前回の画像を再掲します。

PICUSBIOBASICで表示した謎の数値は?
左端はW65C02のクロックbナす。
BASICプログラムによってW65C02にクロックパルスを送っています。
そのクロックパルスを出力した回数を表示しています。
その右はW65C02がクロックの進行に合わせてプログラムを実行する過程でW65C02から出力されたアドレスの下位8ビットです。
ハードウェアが複雑になってしまうので現行のW65C02テストボードではアドレスの下位8ビットしか読み取れません。
その右はメモリから読み出された(またはW65C02から出力された)8ビットのデータです。
さらにその右はPIC18F45K50とW65C02との間で制御信号を入出力しているPORTCの値です。
RC7、RC6はメモリアドレスのA7、A6につながっています。
RC0はW65C07から出力されるSYNC信号です。
回路図は[第16回]にあります。
SYNCはW65C02が命令の第1バイトのオペレーションコードを読み込むクロック期間中Hになります。
RC0が1の時がSYNC=Hです。
一番右にそのSYNCの値を表示しています。
通常はW65C02のクロックは水晶発振回路によって供給されます。
今回のテストではその回路から水晶を外してそこにPICUSBIOBASICによって作成されるクロックパルスを入力しました。
それによってW65C02を1クロック刻みで実行させることができます。
そのようにしながらアドレスバス、データバスの値をPIC18F45K50で読んでそれを表示させているのです。
クロックパルスは今のところ空いているRE2から出力させています。

先ほどの画像の65C02test33b.lstアセンブルリストとその右側のログにあるBASICプログラムによって出力されたデータ列を照合してみてください。
アドレスとSYNC=1を手がかりにしてその両方を照合することで各命令のクロックごとの動作が確認できます。
たとえばアドレス02の9A(TXS)はCLOCK#17の1クロックだけのように見えます。
その次のCLOCK#18はアドレス03になっていてその値A9(LDA)が表示されています。
あれ?
W65C02の命令クロック数は最低でも2クロックだったのでは?
そう思ってよくよく見ますとその行のSYNCは0になっています。
その次のCLOCK#19もアドレス03で変わらずその値もA9で同じです。
しかしその行はSYNC=1になっていてW65C02がここでオペレーションコードを読み込んでいる(本当は先読みしているのかも?)ことがわかります。
また下のほうのサブルーチンコール、リターンのときのメモリに対する動作など解説書などではなかなかわからないような詳細な動きがまさに一目瞭然です。
いや。
これはすごい。
と思っていただけますでしょうか。

W65C02マイコンボードの製作[第50回]
2026.8.21 upload

前へ
次へ
ホームページトップへ戻る