[新連載開始]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
前へ
次へ
ホームページトップへ戻る