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