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


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

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

[第59回]



●JSR,RTS

JSRはサブルーチンコール命令です。
大抵はCALLにするところなのですが。
W65C02はなぜかネーミングにクセがあります。
RTSはサブルーチンからのリターン命令です。
これも普通はRETとかRETURNとかにするところでしょう。
JSR命令は絶対アドレスを指定する命令のみです。
またRTS命令もこの1命令のみです。
どちらもフラグは変化しません。
 ニーモニック  マシン語コード  アセンブラ書式 バイト数 クロック数
 JSR a  20  JSR $1234  3  6
 RTS  60  RTS  1  6

JSRはその次のアドレスの上位バイトが先にスタックにPUSHされ続いて下位バイトがPUSHされます(W65C02ではこの説明は誤りです)。
その後指定したアドレスにジャンプします。
8080やZ80での経験からごくフツーにそのように書いたのですがW65C02ではそこのところがちょっと違っているようです(上記下線部)。
RTSはJSRと逆の動作をします。
この連載記事を書くにあたり下記を参考にさせていただいております(サイトの編集者さまに感謝申し上げます)。
https://en.wikibooks.org/wiki/65c02_Assembly

今回も上記リンクを参照させていただいたところ「え?ほんとうなの?」という記述に気が付きました。
下がその部分です。



JSRの最初のところに
The address before the next instruction(PC−1)
と書いてあります。
え?PCじゃなくてPC−1???
それでRTSのところを見ますと
The return address is incremented and stored in PC
と書いてあります。
うーん。
辻褄は合っていますねえ。
ま。
フツーはどちらでもよいことなのですが細かいデバッグなどではひょっとして気になるところかも。
そこのところがどうなのかも確認できるつもりのテストプログラムを書きました。
下がテストプログラム(ソースプログラム)です。
;w65c02test33 26/8/12 8/20 8/30
;
;JSR,RTS
;
        org $8000
;
        ldx #$ff;set stack pointer
        txs
        phx
        lda #$00
        sta $00
        pha
        jsr jp1
        inc
        sta $02
        stp
;
        nop
        nop
        nop
;
jp1:
        inc
        sta $01
        rts
;end

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

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

0000        ;w65c02test33 26/8/12 8/20 8/30
0000        ;
0000        ;JSR,RTS
0000        ;
8000            org $8000
8000        ;
8000 A2FF       ldx #$ff;set stack pointer
8002 9A         txs
8003 DA         phx
8004 A900       lda #$00
8006 8500       sta $00
8008 48         pha
8009 201380     jsr jp1
800C 1A         inc
800D 8502       sta $02
800F DB         stp
8010        ;
8010 EA         nop
8011 EA         nop
8012 EA         nop
8013        ;
8013        jp1:
8013 1A         inc
8014 8501       sta $01
8016 60         rts
8017        ;end

アドレス8009がJSR JP1です。
この命令が実行される時点でPC(プログラムカウンタ)はその次の命令のアドレス(800C)になっているはずで8080やZ80なら800Cをリターン先のアドレスとしてスタックにPUSHするところなのですが…。

65C02TEST33C.BINをロードして/RUNを実行しました。


/RUN実行後に/DM 00を実行してゼロページを表示させました。

最初に$00に00を入れてサブルーチンをコールします。
サブルーチンJP1では$01に01を入れたあとリターンします。
メインルーチンに戻った後で$02に02を入れてプログラムを終了します。
$00〜$02がその通りになっていますからプログラムが正しく実行されたことは確認できました。
それで問題のスタックはといいますと。
/DM 01でスタックを表示させました。

最初にSP=FFにしてからFFをPUSHし続いて00をPUSHしました。
その後にPCの値としてまずは上位アドレスの80をPUSHします。
そのようになっていますね。
続いて下位アドレスをPUSHします。
おや。
0Bですね。
PCの下位アドレスなら0Cです。
なるほど。
確かにPC−1です。
納得です。
しかしなぜなのでしょう?
フツーにPCの値をそのままPUSHしてそしてそのままPOPしてリターンしたほうがよさそうなものですけれど。
わざわざPC−1をPUSHしてそしてリターンするときにはその値+1をPCに入れるなんて。
ちょいと謎ですね。
ま。
どーでもよいことなのでしょうけれど。

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

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