現在地

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


カテゴリー:

最後となる今回は「3. メモリに退避されている内容をレジスタに戻しユーザプログラムに制御を渡す」です。

コマンドで値を変更したらその状態でユーザプログラムを実行できなくては意味がありません。

要はレジスタに値を設定して目的の番地にブランチすれば良いだけなのですが、すでに設定済みのレジスタを壊さないようにしなくてはいけないので進むにつれ制約が増えていきます。

比較的多くのプロセッサで使える手は、「スタックに積んでおいてPOP,...,POP,RET」です。ちょうど1回目の逆です。

スタックを使った割り込みに対応しているプロセッサなら大抵これが使えます。

割り込み時にはレジスタの状態を元に戻す必要があるからです。スタックが専用空間にあって自由にアクセスできないなど使えないプロセッサもありますが...

MC6800を例に見てみましょう。

     329/    E1F1 : 9E E0               	LDS	REGSP
     330/    E1F3 :                     GO1:
     331/    E1F3 : 96 E3               	LDAA	REGPC+1
     332/    E1F5 : 36                  	PSHA			; PC(L)
     333/    E1F6 : 96 E2               	LDAA	REGPC
     334/    E1F8 : 36                  	PSHA			; PC(H)
     335/    E1F9 : 96 DF               	LDAA	REGX+1
     336/    E1FB : 36                  	PSHA			; X(L)
     337/    E1FC : 96 DE               	LDAA	REGX
     338/    E1FE : 36                  	PSHA			; X(H)
     339/    E1FF : 96 DC               	LDAA	REGA
     340/    E201 : 36                  	PSHA			; A
     341/    E202 : 96 DD               	LDAA	REGB
     342/    E204 : 36                  	PSHA			; B
     343/    E205 : 96 E4               	LDAA	REGCC
     344/    E207 : 36                  	PSHA			; CC
     345/    E208 : 3B                  	RTI

MC6800はSWISP以外のレジスタをスタックに積むので、それと同じ構造をスタック上に作っておいてRTIを実行すれば良いです。

SPは329行目で事前にセットしておきます。この後PSHAで変化してしまいますが、RTIの実行完了時には辻褄が合います。

331行目からはRTI命令で目的のレジスタに入るよう順番を考えてスタックに積んでいきます。

最後にRTIを実行して完了です。

もしRTI相当の命令で扱われないレジスタがあるときはこの例のSP同様事前にセットしておきます。

3回に分けて書いたこのテクニック、モニタ・デバッガ以外にも使い道があります。

ここではメモリへの保存場所は1つでしたが、これを複数にすると何ができるでしょうか?

例えばタイマ割り込みがかかって保存場所Aに保存し、保存場所Bにもとづいて実行開始します。次のタイマ割り込みでは保存場所Bに保存し、保存場所Aを用いて実行開始します。

これを繰り返せばタイマ割り込みごとに2つのプログラムを交互に少しずつ実行する状態になります。ということでマルチタスクができてしてしまいました。2つのプログラム間で同期する機能などを足していけば原始的なRTOSも実現できます。


コメントを追加

Plain text

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