[新連載開始]W65C02マイコンボードの製作
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
私としてはW65C02をさわるのは全く初めてです。何から何まで未経験です。さてどうなりますでしょうか。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第62回]
●BRK,NOP,STP
NOPはNo Operationです。
何もしない命令です。
実行によってフラグやレジスタに影響を与えません。
単にプログラムのアドレスを調整するとかパルス出力幅を調整する「時間稼ぎ」のためなどに使われます。
STPはプログラムの実行を停止して静止モードになります。
後の回で説明する予定のWAIと違って割込みによって静止を解除することはできません。
外部からのリセット入力によってのみ解除できます。
NOPとSTPはこれまでの回でテストプログラムに使ってきていますのであらためてテストプログラムは作成しません。
今回の主役はBRKです。
BRKの説明に入る前にまずは各命令のコードなどについて下にまとめておきます。
| ニーモニック | マシン語コード | アセンブラ書式 | バイト数 | クロック数 |
| BRK | 00 | BRK | 1 | 7 |
| NOP | EA | NOP | 1 | 2 |
| STP | DB | STP | 1 | − |
BRKはソフトウェア割込み命令です。
BフラグとIフラグがセットされます。
Bフラグ(ビット4)はBreakフラグです。
Iフラグ(ビット2)は割込み禁止フラグです。
BRKはプログラムデバッグのための特殊な割込み命令として用意されたと理解しています。
Z80や8080のRST7(コードFF)と同じ用途です。
プログラムのデバッグをしたいときにブレークをさせたいところにこの命令(実用上は命令コード)を上書きします。
その使い方からデバッグの対象はRAM上のプログラムということになります。
RST7と違ってコードが00なのでROMのプログラムでも上書き可能であるという解説をネット上で見ました。
コードが00なのはそういう理由からかもしれません。
通常の割込みと異なり割り込み禁止フラグ(Iフラグ)の状態に関係なく実行可能です。
通常の割込みと同じで割込みジャンプテーブル(アドレスFFFE、FFFF)に記載されたアドレスにジャンプするので事前にBRKサービスプログラムのアドレスを書いておきます。
BRK割込みが発生するとその時点のPC(プログラムカウンタ)に+2した値とフラグレジスタの値をスタックにPUSHした後にBRKサービスプログラムにジャンプします。
そのあたりの確認ということも含めてテストプログラムを作成しました。
;w65c02test36 26/8/13
;
;BRK
;
org $8000
;
lda #$10
sta $fffe
lda #$80
sta $ffff
ldx #$fd
txs
cli
bra start
;
braek:
tsx
stx $01
stp
;
start:
stx $00
inc
adc #$12
sta $03
brk
tsx
stx $02
stp
;end
|
W65C02アセンブラでアセンブルしました。

下はアセンブルの結果作成されたアセンブルリストです。
0000 ;w65c02test36 26/8/13 0000 ; 0000 ;BRK 0000 ; 8000 org $8000 8000 ; 8000 A910 lda #$10 8002 8DFEFF sta $fffe 8005 A980 lda #$80 8007 8DFFFF sta $ffff 800A A2FD ldx #$fd 800C 9A txs 800D 58 cli 800E 8004 bra start 8010 ; 8010 braek: 8010 BA tsx 8011 8601 stx $01 8013 DB stp 8014 ; 8014 start: 8014 8600 stx $00 8016 1A inc 8017 6912 adc #$12 8019 8503 sta $03 801B 00 brk 801C BA tsx 801D 8602 stx $02 801F DB stp 8020 ;end |
上で書きましたように本来はデバッグするのが目的なのでプログラム中に書いておくのではなくでデバッグのときにブレークしたいところにBRKコードを上書きするという使い方になるかと思いますが今回はテストなのでプログラム中に置いてあります。
BRKはソフトウェア割込みであることを除けば通常の外部割込み(IRQ端子から入力)と同じです。
後でわかったことですが外部割込みと違ってBRKはIフラグの状態に関係なく実行可能なのだそうです(後で確認します)。
BRKが実行されるとシステムジャンプテーブルFFFE、FFFFに書いてあるアドレスにジャンプします。
今回のテストプログラムではプログラムの先頭でBRKプログラムの先頭アドレス(8010)をFFFE、FFFFに入れておきます。
そしてスタックポインタにスタックの先頭アドレスとしてFDを入れるとともに記録として$00にも同じスタックポインタの値(FD)を入れます。
スタックについてちょっとまだ迷いがあったころに書いたプログラムなのでFDなどというハンパな値を設定しています。
最初にこのプログラムを書いた時点ではBRKの実行にはIフラグ=0が条件かと誤解していましたのでCLI命令を使っています。
BRKプログラムによってスタックに保存されるフラグレジスタの値を確認する目安になるようにBRK命令の直前に実行される演算の結果の値(アキュムレータの値)を$03にセーブしておきます。
プログラムはアドレス801Bでブレークします。
BRKプログラムが実行されたことがわかるようにアドレス$01にそのときのスタックポインタの値を入れます。
BRKプログラムの最後にSTPがありますからそこで停止します。
BRKが正しく実行されればアドレス801Cから後ろは実行されないはずです。
もし実行されたら$02にそのときのスタックポインタの値が入ります。
65c02test36.binをロードしました。
実行前に$00〜$03をFFにしておきます。

/RUNでプログラムを実行しました。
実行後に/CMで確認したところ次の通りでした。
0000 FD プログラム開始時のスタックポインタの値
0001 FA BRKプログラムにエントリしたときのスタックポインタの値
0002 FF 変化なし
0003 93 アキュムレータの値
0002が変化なしなので801C以後は実行されなかったことがわかりました。
/DM 01を実行してスタックエリアを表示させました。

BRKが読み込まれたときのプログラムカウンタの値+2がスタックに保存されます。
BRKは801Bにあります。
スタックにはその値+2が入りますから801B+2=801Dです。
おお。
合ってますね。
次はフラグです。
01FBにはフラグレジスタの値が入ります。
B0です。
BRKの直前にINCとADC #$12が実行されています。
その前のアキュムレータの値は$80です。
80+1+12=93ですから$03の値と一致しています。
そのときのフラグはN=1、V=0、Z=0、C=0ですがBRKの実行によってB(ビット4)とI(ビット2)がセットされますから10110100(B4)になるはずなのですが。
あれ?
ビット2が0?
で。
Google様にお聞きしましたら。
Iフラグは直前の値をそのままスタックに退避するのだそうです。
なるほどそれで0になるということか。
その後にCPU内部で割込み禁止にするためIフラグがセットされるのだそうです。
ついでにDフラグ(ビット3。十進モードフラグ)は強制的にクリアされるのだそうです。
うむむ。
よくわからん仕様であります。
上の方に書きましたが。
確かGoogleで確認したときBRKはIフラグに関係なく実行されると書いてあったような。
再確認したところ確かにそう書いてありました。
ならば。
再テストするよりほかはないでしょう。
そこを意識してあえてIフラグをセットしてテストしました。
CLIをSEIに変更しました。
;w65c02test36b 26/8/13
;
;BRK
;
org $8000
;
lda #$10
sta $fffe
lda #$80
sta $ffff
ldx #$fd
txs
sei
bra start
;
braek:
tsx
stx $01
stp
;
start:
stx $00
inc
adc #$12
sta $03
brk
tsx
stx $02
stp
;end
|
W65C02アセンブラでアセンブルしました。
0000 ;w65c02test36b 26/8/13 0000 ; 0000 ;BRK 0000 ; 8000 org $8000 8000 ; 8000 A910 lda #$10 8002 8DFEFF sta $fffe 8005 A980 lda #$80 8007 8DFFFF sta $ffff 800A A2FD ldx #$fd 800C 9A txs 800D 78 sei 800E 8004 bra start 8010 ; 8010 braek: 8010 BA tsx 8011 8601 stx $01 8013 DB stp 8014 ; 8014 start: 8014 8600 stx $00 8016 1A inc 8017 6912 adc #$12 8019 8503 sta $03 801B 00 brk 801C BA tsx 801D 8602 stx $02 801F DB stp 8020 ;end |
先ほどと同じようにテストしました。
65c02test36b.binをロードしました。
$00〜$03をFFにしてから/runを実行しました。

/CMコマンドで$00〜$03を確認して先ほどと同じ結果であることが確認できました。
$01がFAになりましたからIフラグがセットされていてもBRKが実行されることが確認できました。
/DMコマンドでスタックを表示させました。

W65C02マイコンボードの製作[第62回]
2026.9.2 upload
前へ
次へ
ホームページトップへ戻る