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


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

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

[第57回]



●PHA,PHX,PHY,PHP,PLA,PLX,PLY,PLP

PHxはレジスタの値をスタックにPUSHする命令です。
フラグに影響を与えません。
PHxには以下の命令があります。
 ニーモニック  マシン語コード  アセンブラ書式 バイト数 クロック数
 PHA  48  PHA  1  3
 PHX  DA  PHX  1  3
 PHY  5A  PHY  1  3
 PHP  08  PHP  1  3

PHAはアキュムレータの値をスタックにPUSHします。
PHXはXレジスタの値をスタックにPUSHします。
PHYはYレジスタの値をスタックにPUSHします。
PHPはフラグレジスタの値をスタックにPUSHします。

PLxはスタックからレジスタに値を戻します。
8080、Z80ではPOPと言いますがW65C02ではPULLと言います。
PLxには以下の命令があります。
 ニーモニック  マシン語コード  アセンブラ書式 バイト数 クロック数
 PLA  68  PLA  1  4
 PLX  FA  PLX  1  4
 PLY  7A  PLY  1  4
 PLP  28  PLP  1  4

PLAはアキュムレータにスタックから値を戻します。
PLXはXレジスタにスタックから値を戻します。
PLYはYレジスタにスタックから値を戻します。
PLPはフラグレジスタにスタックから値を戻します。
PLA、PLX、PLYはフラグに影響を与えませんがPLPはスタックから戻した値でフラグが書き換えられます。

この連載記事に記載の各命令のクロック数は下記サイトから引用させていただいています(感謝です)。
https://www.zophar.net/fileuploads/2/10533qqcap/6502ref.html
ところが今回の記事を書くにあたって上記から引用させていただこうとしましたところなぜかPHPとPLPが見当たりません。
多分ほかのPHA、PLAなどと同じだろうとは思いましたがいいかげんなことを書くわけにもいきません。
どこかに書いてないかと思ってGoogle様に聞いてみましたところ。

すごい!
さすがはAI!
むむむ。
どこからかき集めてくるのでしょう?
んでも。
Google様はときどきウソをおっしゃいますので鵜呑みにはできませんです。
やっぱりねえ。
わからないことは自分で汗をかいて確かめるべきであります。
で。
自ら確認をいたしました。
確認に使ったテストプログラムです。
0000        ;w65c02test30 26/8/12
0000        ;
0000        ;PHP,PLP
0000        ;
8000            org $8000
8000        ;
8000        loop:
8000 08         php
8001 28         plp
8002 80FC       bra loop
8004        ;end

PHPとPLPだけを繰り返します。
下はその様子をカメレオンロジアナで観測した波形です。

いままで作成したテストプログラムはW65C02テストボードでクロック14MHzで確認をしています。
今のところ14MHzでしっかり安定して動作しています。
しかし以前カメレオンロジアナで波形の確認をしようとしてプローブを沢山つけたところ14MHzでは誤作動してしまいました。
ですので今回のロジアナでの観測はCPUクロック10MHzでおこないました。
実行クロック数が分かればいいのでアドレスA0〜A3とPUSH時のWR信号とCPUCLOCKのみの観測です。
PUSH、PULLの期間はアドレスから推測しました。
確かにPUSHは3クロック、PULLは4クロックのようです。

クロックについて納得しましたのでいつものようにテストプログラムを作ってテストをしました。

;w65c02test31 26/8/12
;
;PHA,PHXZ,PHY,PHP,PLA,PLX,PLY,PLP
;
        org $8000
;
        ldx #$fd
        txs
        lda #$12
        sta $00
        pha
        ldx #$34
        stx $01
        phx
        ldy #$56
        sty $02
        phy
;
        lda #$00
        clc
        adc #$00
        php
        lda #$7f
        adc #$7f
        php
;
        ply
        sty $03
        ply
        sty $04
;
        lda #$00
        ldx #$00
        ldy #$00
        sta $10
        stx $11
        sty $12
        ply
        sty $22
        plx
        stx $21
        pla
        sta $20
;
        ldx #$ef
        txs
        lda $03
        pha
        plp
        phy
        php
;
        tsx
        stx $05
        stp
;end

W65C02アセンブラでアセンブルしました。

下はアセンブルした結果作成されたアセンブルリストです。

0000        ;w65c02test31 26/8/12
0000        ;
0000        ;PHA,PHXZ,PHY,PHP,PLA,PLX,PLY,PLP
0000        ;
8000            org $8000
8000        ;
8000 A2FD       ldx #$fd
8002 9A         txs
8003 A912       lda #$12
8005 8500       sta $00
8007 48         pha
8008 A234       ldx #$34
800A 8601       stx $01
800C DA         phx
800D A056       ldy #$56
800F 8402       sty $02
8011 5A         phy
8012        ;
8012 A900       lda #$00
8014 18         clc
8015 6900       adc #$00
8017 08         php
8018 A97F       lda #$7f
801A 697F       adc #$7f
801C 08         php
801D        ;
801D 7A         ply
801E 8403       sty $03
8020 7A         ply
8021 8404       sty $04
8023        ;
8023 A900       lda #$00
8025 A200       ldx #$00
8027 A000       ldy #$00
8029 8510       sta $10
802B 8611       stx $11
802D 8412       sty $12
802F 7A         ply
8030 8422       sty $22
8032 FA         plx
8033 8621       stx $21
8035 68         pla
8036 8520       sta $20
8038        ;
8038 A2EF       ldx #$ef
803A 9A         txs
803B A503       lda $03
803D 48         pha
803E 28         plp
803F 5A         phy
8040 08         php
8041        ;
8041 BA         tsx
8042 8605       stx $05
8044 DB         stp
8045        ;end


Aに12、Xに34、Yに56を入れてPUSHするとともに$00〜$02にストアしておきます。
2つの加算後のフラグもそれぞれPUSHします。
演算する度に結果の値とフラグをスタックにPUSHします。
PUSHしたフラグの値はYレジスタにPULLして$03と$04にストアします。
PUSH、PULLの確認は後でスタックエリアを/DM 01で読み込んで確認することができますがここではまずはゼロページにアキュムレータ、X、Yの値をストアすることで確認するようにしました。
アキュムレータ、X、Yをクリアして$10〜$12にストアします。
そのあとスタックからPULLした値を$20〜$22にストアします。
フラグに対してはちょっと確認が面倒なのですがスタックポインタを$EFに設定してPLPとPHY、PHPを組み合わせて確認をしました。
03の値(7F+7F加算後のフラグF4)をPUSHした後PULLでフラグレジスタに戻しYレジスタの値(22に戻した56)とフラグ(F4)をPUSHし最後にそのときのスタックポインタの値を05に入れます。
EFからPUSH、PULL、PUSH、PUSHなのでEDになります。

$03と$04はフラグの値です。
PUSH、PULLの関係で順序が逆になっています。
$03は2回目のADCを実行した後のフラグ(N=1、V=1、Z=0、C=0)です。
2番目のADCはEF+EFです(結果はFE)。
$04は最初のADCを実行した後のフラグ(N=0、V=0、Z=1、C=0)です。
最初のADCは00+00です(結果は00)。

プログラムをスタートした後でスタックポインタにFDをセットしてA=12、X=34、Y=56をPUSHした後00+00の結果のフラグとEF+EFの結果のフラグをPUSHしました。
スタックの値はアドレスFDから前に12、34、56、36、F4です。
その後PUSHしたフラグの値F4と36はPULLして03と04に格納しました。
さらにPULLを実行してY、X、Aに戻した値を22、21、20に格納しました。
スタックポインタをEFにした後のスタックはEFが56でEEがF4です。
ずっと8080やZ80を使ってきた経験からするとスタックポインタの値をつい誤解してしまいます。
8080、Z80ではスタックポインタ(SP)は最後にPUSHしたときのスタックアドレスを示しています。
次にPOPするときはそのSPアドレスとSP+1の値を読みます。
PUSHするときはSP−1とSP−2に値を入れます。
つまりSPはスタックの終わりのアドレスを示しています。
W65C02ではSPはスタックの終わりのアドレス−1を示しています。
W65C02では次にPUSHするときはSPとSP−1に値を入れます。
逆にPULLするときはSP+1、SP+2の値を読むことになります。
うーん。
ややこしい!
今回も余り出来のいいテストプログラムではありませんでしたが命令の確認、動作の確認は出来たと思いますのでこれでよいということにいたしましょう。

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

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