現在地

[UniMon] レジスタ命令の内側(その1)


カテゴリー:

MC6800に続いて6502, MC6809についてもレジスタ命令を追加しましたので、その内側について書いてみたいと思います。

さて、レジスタ命令とはレジスタの値を表示・変更する機能なわけですが、CPUがある瞬間に実行できるプログラムは1つですからユーザプログラム実行中はモニタプログラムは実行できません。モニタプログラム自身の動作にもレジスタは必要です。

ではどうするか?

モニタプログラムには次の3つの機能が必要になります。

  1. ユーザプログラムからモニタに制御が渡ったときにレジスタ内容をメモリに退避する
  2. メモリに退避されている値を表示・変更する
  3. メモリに退避されている内容をレジスタに戻しユーザプログラムに制御を渡す

まず1.ですがプログラムカウンタPCの値を知る必要があるのでCALL, BSR(Branch Subroutine)のような命令が最低限必要です。さらにユーザプログラムを書き換えて埋め込むので通常短い命令が使われます。今回MC6800, MC6809ではSWI(Software Interrupt)を、6502ではそのものズバリのBRKを使いました。どちらも1バイト命令です。

これらの命令を実行すると割り込みベクタ経由でモニタに制御が渡ってきます。

スタックに積まれていないレジスタがあればそれを優先的に退避します。未退避のレジスタを壊さないよう注意が必要です。幸いSWIはほとんどをスタックに積んでくれるので楽ですが、Z80などでは順序をよく考えないといけないでしょう。

専用の退避場所を設けずスタックに積んだままにする手もありますが、スタックポインタを変更するとき面倒なことになるので避けたほうが良いと思います。

プロセッサによっては(SC/MPとか)この処理が書けず、どうしても一部のレジスタを保存できません。

6502を例に見てみることにします。

     716/    FC56 :                     	;; Interrupt / Break
     717/    FC56 :                     IRQBRK:
     718/    FC56 : =>TRUE              	IF USE_REGCMD
     719/    FC56 : 48                  	PHA
     720/    FC57 : 08                  	PHP
     721/    FC58 : 68                  	PLA			; A <= PSR
     722/    FC59 : 29 10               	AND	#$10		; Check B flag
     723/    FC5B : F0 2C               	BEQ	IBIR
     724/    FC5D : D8                  	CLD
     725/    FC5E :                     	
     726/    FC5E : 68                  	PLA			; A
     727/    FC5F : 85 1C               	STA	REGA
     728/    FC61 : 8A                  	TXA			; X
     729/    FC62 : 85 1D               	STA	REGX
     730/    FC64 : 98                  	TYA			; Y
     731/    FC65 : 85 1E               	STA	REGY
     732/    FC67 : 68                  	PLA			; PSR (Pushed by BRK)
     733/    FC68 : 85 22               	STA	REGPSR
     734/    FC6A : 68                  	PLA			; PC(L) (Pushed by BRK)
     735/    FC6B : 38                  	SEC
     736/    FC6C : E9 02               	SBC	#2		; Adjust PC to point BRK instruction
     737/    FC6E : 85 20               	STA	REGPC
     738/    FC70 : 68                  	PLA			; PC(H) (Pushed by BRK)
     739/    FC71 : E9 00               	SBC	#0
     740/    FC73 : 85 21               	STA	REGPC+1
     741/    FC75 : BA                  	TSX			; SP
     742/    FC76 : 86 1F               	STX	REGSP
     743/    FC78 :                     
     744/    FC78 : A9 ED               	LDA	#low(BRKMSG)
     745/    FC7A : 85 27               	STA	PT0
     746/    FC7C : A9 FC               	LDA	#high(BRKMSG)
     747/    FC7E : 85 28               	STA	PT0+1
     748/    FC80 : 20 88 FB            	JSR	STROUT
     749/    FC83 : 20 20 FB            	JSR	RDUMP
     750/    FC86 : 4C 36 F8            	JMP	WSTART
     751/    FC89 :                     
     752/    FC89 :                     IBIR:
     753/    FC89 : 68                  	PLA
     754/    FC8A : 40                  	RTI
     755/    FC8B : =>FALSE             	ELSE			; USE_REGCMD
     756/    FC8B :                     	;; Dummy
     757/    FC8B :                     	RTI
     758/    FC8B : [718]               	ENDIF			; USE_REGCMD

6502は割り込みIRQとBRKでベクタを共有しているので719~723行目で分離します。

ユーザプログラム内でDフラグがどうなっているか不明なので724行目でクリアしておきます。これがセットされていると加減算がBCD処理になってしまうからです。

726~742行目で各レジスタをメモリに退避していきます。736行目付近でPCを-2しているのはBRK命令のアドレスになるよう補正しているため、BRK命令を本来の命令に戻して継続実行する際に便利なようにです。

その後BRKが実行されたことを表示し、全レジスタをダンプします。もうレジスタの退避は完了しているのでレジスタは自由に使えます。

最後に750行目でモニタのコマンド待ちになります。今回モニタはユーザプログラムのスタックエリアをそのまま使う形になりますが、エリアを分ける(742行目の後でLDX #****,TXSなどとする)ことも可能です。このモニタのスタック消費はそれほどでもないので分けることはしませんでした。

次回は表示・変更コマンドについて書きたいと思います。


コメントを追加

Plain text

  • HTMLタグは利用できません。
  • ウェブページアドレスとメールアドレスは、自動的にハイパーリンクに変換されます。
  • 行と段落は自動的に折り返されます。
※ コメントは原則公開です。個別のご相談などは「ご意見・ご要望」からお願いします。