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


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

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

[第60回]



●CLC,SEC,CLD,SED,CLI,SEI,CLV

今回説明する命令はW65C02のフラグレジスタの各ビットをセット、リセットする命令です。
8080、Z80のフラグレジスタはFレジスタです(まんまでわかりやすい)。
W65C02ではPレジスタ(Processor status register)です(うーん。直感的ではないなあ)。
Pレジスタのビット配置は下の通りです(左が上位ビット7で右が下位ビット0です)。

N V − B D I Z C

Nはサインフラグです。演算の結果が負のときにセット、正または0のときにクリアされます。
Vはオーバーフローフラグです。演算の結果がオーバーフローしたときにセットされます。
第5ビットは使用されません。
Bはブレークフラグです。ソフトウエア割込み(BRK)が実行されたときにセットされます。
Dは十進演算指定フラグです。セットされているときADC、SBCが十進演算モードになります。
Iは割込み禁止フラグです。セットされているとき外部割込みが禁止されます。NMB(ノンマスカブルインタラプト)、BRKには働きません。
Zはゼロフラグです。演算の結果が0のときにセット、それ以外のときにクリアされます。
Cはキャリーフラグです。ADCで上位桁にキャリーが発生したときにセットされます。SBCでは逆にボローがあるときにクリアされます(そこのところがどうもわからんなあ)。
次の命令があります。
Nフラグ、Bフラグ、Zフラグに対する命令はありません。
またVフラグをセットする命令もありません。
 ニーモニック  マシン語コード  アセンブラ書式 バイト数 クロック数
 CLC  18  CLC  1  2
 SEC  38  SEC  1  2
 CLD  D8  CLD  1  2
 SED  F8  SED  1  2
 CLI  58  CLI  1  2
 SEI  78  SEI  1  2
 CLV  B8  CLV  1  2

CLCはCフラグをクリアします。
SECはCフラグをセットします。
CLDはDフラグをクリアします。
SEDはDフラグをセットします。
CLIはIフラグをクリアします。
SEIはIフラグをセットします。
CLVはVフラグをクリアします。

下はテストプログラム(ソースプログラム)です。
;w65c02test34 26/8/12 8/31
;
;flag set,reset
;
        org $8000
;
        ldx #$ff
        txs
        clc
        lda #$80
        adc #$80
        php
        sta $00
        clc
        clv
        php
        lda #$00
        adc #$00
        php
        sta $01
        lda #$56
        adc #$78
        php
        sta $02
        sed
        lda #$56
        adc #$78
        php
        sta $03
        cld
        sec
        php
        lda #$56
        adc #$78
        php
        sta $04
        sei
        php
        cli
        php
        tsx
        stx $05
        stp
;end

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

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

0000        ;w65c02test34 26/8/12 8/31
0000        ;
0000        ;flag set,reset
0000        ;
8000            org $8000
8000        ;
8000 A2FF       ldx #$ff
8002 9A         txs
8003 18         clc
8004 A980       lda #$80
8006 6980       adc #$80
8008 08         php
8009 8500       sta $00
800B 18         clc
800C B8         clv
800D 08         php
800E A900       lda #$00
8010 6900       adc #$00
8012 08         php
8013 8501       sta $01
8015 A956       lda #$56
8017 6978       adc #$78
8019 08         php
801A 8502       sta $02
801C F8         sed
801D A956       lda #$56
801F 6978       adc #$78
8021 08         php
8022 8503       sta $03
8024 D8         cld
8025 38         sec
8026 08         php
8027 A956       lda #$56
8029 6978       adc #$78
802B 08         php
802C 8504       sta $04
802E 78         sei
802F 08         php
8030 58         cli
8031 08         php
8032 BA         tsx
8033 8605       stx $05
8035 DB         stp
8036        ;end

フラグのセット、リセットの結果を確認するためにPフラグをスタックにPUSHしてプログラム実行後にスタックを確認します。
Dフラグのセット、クリアによって計算結果がどう変わるかも見てみます。
最初にスタックポインタをFFにします。
1)Cフラグをクリアしてから80+80の計算をします。
結果のフラグをスタックにPUSHし結果の値を$00に入れます。
2)CLC、CLVコマンドの確認です。
実行後にフラグをPUSHします。
3)00+00の計算を行い結果のフラグをPUSHし結果の値を$01に入れます。
4)56+78の計算を行い結果のフラグをPUSHし結果の値を$02に入れます。
5)Dフラグをセットしてから56+78の計算を行い結果のフラグをPUSHし結果の値を$03に入れます。
6)Dフラグをクリアし、Cフラグをセット(SECコマンドの確認)してから56+78の計算を行い結果のフラグをPUSHし結果の値を$04に入れます。
7)SEI(Iフラグをセットする)を実行してからフラグをPUSHします。
8)CLI(Iフラグをクリアする)を実行してからフラグをPUSHします。
9)最後にスタックの値を$05に入れます。

65c02test34b.binをロードして実行しました。

/DM 00でゼロページの値を確認しました。
1)80+80=00です(上位桁にキャリー)。$00は00になっています。OKです。
3)00+00=00です(繰り上がりはありません)。$01は00になっています。OKです。
4)56+78=CEです(上位桁にキャリー)。$02はCEになっています。OKです。
5)十進加算です。Dフラグをセットしてから56+78を計算しました。結果は34です(上位桁にキャリー)。$03は34になっています。OKです。
6)DフラグをクリアしCフラグをセットしてから56+78を計算しました。結果はCFです(上位桁にキャリー)。$04はCFになっています。OKです。
9)スタックポインタの値を$05に入れました。PUSHを9回実行しましたからFF−9=F6です。$05はF6になっています。OKです。

/DM 01でスタックを表示させました。

1)80+80=00の計算によってN(サインフラグ)=0、V(オーバーフローフラグ)=1、Z(ゼロフラグ)=1、C(キャリーフラグ)=1になります。
ビット6は常時1のようです。
ハードウェアリセットによりDフラグはクリアされIフラグはセットされます(そのようです)。
011000111=67のはずなのですが。
あれ?
01110111=77?
Bフラグはなぜセットされているのでしょう?
BRKなどしていないのですけれど。
Bフラグについては後ほど確認をしてみます。
2)CLC、CLVを実行しましたからフラグは00110110=36になります(Bは後ほど確認します)。
3)00+00=00の計算によってZフラグがセットされます。
00110110=36です。
4)56+78=CEの計算によってN=1、V=1、Z=0、C=0になります。
Vフラグは符号付演算(−128〜+127の間の加減算)で結果がその範囲を超えるとセットされます。
今回の計算では上位桁にキャリーはありませんからC=0です。
11110100=F4です。
5)56+78=34(十進加算)です。
N=0、V=1、D=1、Z=0、C=1になります。
01111101=7Dです。
6)DフラグをクリアしCフラグをセットしてからフラグをPUSHしました。
01110101=75です。
56+78=CFを計算しました。
N=1、V=1、D=0、Z=0、C=0になります。
11110100=F4です。
7)Iフラグをセットしました。
11110100=F4です。
8)Iフラグをクリアしました。
11110000=F0です。

さて。
問題のBフラグです。
いつものようにGoogle様に聞いてみました。

おお。
なるほど。
BRKだけではなくてPHPを実行したときもBフラグはセットされるのだそうです。
納得です。
ですけれど。
なんでそんなことになってるのさ。
W65C02の謎仕様でありますね。
それはそれとしまして。
GoogleAIはすごい!

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

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