2019-12-28 23:05 — asano
カテゴリー:
最後となる今回は「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はSWI
でSP
以外のレジスタをスタックに積むので、それと同じ構造をスタック上に作っておいてRTI
を実行すれば良いです。
SP
は329行目で事前にセットしておきます。この後PSHA
で変化してしまいますが、RTI
の実行完了時には辻褄が合います。
331行目からはRTI
命令で目的のレジスタに入るよう順番を考えてスタックに積んでいきます。
最後にRTI
を実行して完了です。
もしRTI
相当の命令で扱われないレジスタがあるときはこの例のSP
同様事前にセットしておきます。
3回に分けて書いたこのテクニック、モニタ・デバッガ以外にも使い道があります。
ここではメモリへの保存場所は1つでしたが、これを複数にすると何ができるでしょうか?
例えばタイマ割り込みがかかって保存場所Aに保存し、保存場所Bにもとづいて実行開始します。次のタイマ割り込みでは保存場所Bに保存し、保存場所Aを用いて実行開始します。
これを繰り返せばタイマ割り込みごとに2つのプログラムを交互に少しずつ実行する状態になります。ということでマルチタスクができてしてしまいました。2つのプログラム間で同期する機能などを足していけば原始的なRTOSも実現できます。
コメントを追加