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