MICROSの制作
I.目的
2つのユーザプログラムがマルチプログラム方式で走るOSを作る。TSSのようなタイムスライスは行わず、あるプロセスがキーボード入力でWAIT状態になった時、他のREADY状態のプロセスが走る。
今回は、さらに単純化し(次に示す)2つのユーザプログラムが走ればよい。
(1) ユーザプログラム1:一文字読んでは1文字書き出すことを繰り返すフォアグラウンプログラム
USRPR1 READ U1DA,U1LEN
OUT U1DA,U1LEN
JUMP USRPR1
U1DA DS 1
U1LEN DS 1
(2)ユーザプログラム2:LD,STを繰り返すバックグラウンドプログラム
USRPR2 LD GR4,U2DC1
ST GR4,U2DA
JUMP USRPR2
U2DC1 DC 1
U2DA DS 1
(注:バックグラウンドは、フォアグラウンドが入力待ちの間だけ走る。)
(注:状態判定がないため、プロセス切換えに伴うフラグレジスタの退避が不要)
II.使用ソフトウエア
CASL2をマルチプログラミング用に改造したものCASL2xを使用。
改造点は次の2点
(1) IN命令の処理をスレッド化しメインのスレッドと並行して動作するようにした。
(2)次の4つの命令を追加する
(a)READ :ユーザが使える入力命令
第1オペランド:入力領域、第2オペランド:入力文字数が入る番地
(注:この命令の中で、SVC(superviser Call)SCINを発生)
(b)LPSW(Load PSW):メモリに格納されている番地へ飛ぶ(OSのみ使用可)
オペランド:ジャンプ先の入っているアドレス
(c)IDLE:ユーザモードになりひたすらIDLEを繰り返す(OSのみ使用可)
(どんな時に使うか:RUNプロセスがない時、IO割り込みを待つ時)
(d)SIO (StartIO):IOデバイスに動作開始を指示。
(ユーザがREAD命令で入力を指示すると、GR6に入力データを格納する番地、GR7に入力文字数を入れる番地、を格納してSystem Callの割込み(割出し)を起こす。この割出しで制御がOSに移ると、その中でSIO命令を出しIOを開始させる。)
(3)MICROS開発ツール
CPUEMディレクトリのinthディレクトリのmainを使用。
III. MICROSのための記憶領域割当て
(1)汎用レジスタの割当て
OS用:GR0,GR1,GR2,GR3;
ユーザ用:GR4,GR5;
標準入出力用:GR6,GR7;(GR6,7を入出力専用に使う。使用禁止)
(2)Main Memoryの割当て
アドレス |
名前 |
機能 |
説明 |
0 |
OPSW |
Old PSW |
割込み発生時にPRが自動保存 |
1 |
IOINT |
入出力割込み |
1文字入力完了時に1が立つ |
2 |
IOSTS |
標準入出力装置の状態 |
IOデバイス使用中は1 |
3 |
SCINT |
SystemCall割出し |
SCINが1を書く |
4 |
IOISA |
割込み処理ルーチン開始番地 |
IOINTが1の時の飛び先番地 |
5 |
SCINSA |
SystemCall処理開始番地 |
SCINTが1の時の飛び先番地 |
6 |
|
|
|
7 |
|
|
|
8 |
RUN |
実行中のプロセス |
Process番号(1又は2) |
9 |
READY |
実行可能プロセス |
Process番号(今回は2or0) |
10 |
WAIT |
IO待ちプロセス |
Process番号(今回は1or0) |
11 |
MOD |
OSモードかUserモードか |
OSモード(1)は割込み禁止 |
12 |
|
|
|
13 |
P1AS |
Process1のPR退避所 |
|
14 |
P1GR4 |
Prosess1のGR4退避所 |
|
15 |
P1GR5 |
Prosess1のGR5退避所 |
|
16 |
|
|
|
17 |
P2SA |
Process2のPR退避所 |
|
18 |
P2GR4 |
Prosess2のGR4退避所 |
|
19 |
P2GR5 |
Prosess2のGR5退避所 |
|
20 |
|
|
|
専用エリア
(特殊レジスタ:0〜3番地はハードウエアがセット、4番地以降はOSがセット)
0番地は割込み発生時のPCを保存する場所(いわゆる旧PSWのPR部)
1番地は割込レジスタ。(IO割込みが発生すると1が立つ)
2番地はIO状態レジスタ。(IOが使用中か否かを示す。Busy=1)
3番地は(READ命令の中で)System Call命令(CASL2のSVC命令SCIN)が1を立てる
4番地はIO割込処理ルーチンの開始番地(IO割込み用、新PSW)
5番地はSCIN処理ルーチンの開始番地(SCIN用、新PSW)
8番地は実行中(RUN)のプロセス番号が入る
9番地は実行可能状態(READY)のプロセス番号が入る
10番地はIO終了待ち(WAIT)のプロセス番号が入る
11番地はOSが走る時1になり、この時は割込み禁止。(CPUエミュレータ内でのみ使用)
13〜15番地はユーザプログラム1(プロセス1)用、退避領域
13番地はユーザプログラム開始番地。PR(Program Counterとも呼ばれる)が退避される
14番地はGR4退避領域
15番地はGR5退避領域
17〜19番地はユーザプログラム2(プロセス2)用、退避領域
17番地はユーザプログラム開始番地。PRが退避される。
18番地はGR4退避領域
19番地はGR5退避領域
IV. 割込み処理(COMET2に追加した機能)
実行モード(11番地)がユーザモード”0”の場合は、命令ファッチ直前にIOINT(1番地)とSCINT(3番地)を調べ、割込みが有ったらPR(PR:program counter)を0番地に退避し、割込みの種類に応じて新PSW(割込み処理ルーチンの開始番地)をPRにセットする。要するに、IO割込みならIOISA、SCIOならSCISAに格納されている番地へ飛ばしす。
(備忘1:割込みが有ったら、すぐOSモードにし、LPSWでUSERモードに戻す)
(備忘2:各割込み処理ルーチンでは先ず、退避されているPSWを各プロセス用退避領域に保存すること)
*IO割込み:IO装置は入出力処理を終わると1番地に1を書き込む。
*READ命令は中で、System Call により3番地に1を書き込む
V. MICROSの動き
MICROSはプロンプト(>)を表示してコマンドを待つ
コマンドは2種類
F:ユーザプログラム1(フォアグラウンド)のみを実行
B:ユーザプログラム2(バックグラウンド)のみを実行
A:両ユーザプログラム(フォアグラウンドとバックグラウンド)を並列実行
VI.プログラムの型紙
MICROS START INIT
;ハードウエアレジスタエリア
OPSW DS 1;OldPSW
IOINT DS 1;IO割り込みは1
IOSTS DS 1;IO状態、0ならREADY、1ならBUSY
SCINT DS 1;SystemCall割出し、SCINは1をセット
IOISA DS 1;割込み処理開始番地
SCINSA DS 1;SystenCallIN割出し処理開始番地
RSV1 DS 2;未使用
;OSエリア
RUN DS 1;実行中のプロセス
READY DS 1;実行可能プロセス
WAIT DS 1;IO終了待ちプロセス
MOD DS 1;OSmode=1,UserMode=0;
RSV2 DS 1;未使用
;ユーザプロセス1用退避エリア
P1SA DS 1;再開アドレス
P1GR4 DS 1;GR4退避
P1GR5 DS 1;GR5退避
RSV3 DS 1;未使用
;ユーザプロセス2用退避エリア
P2SA DS 1;再開アドレス
P2GR4 DS 1;GR4退避
P2GR5 DS 1;GR5退避
RSV4 DS 1;未使用
;OS変数、定数
PPT DC '>'
DC0 DC 0
DC1 DC 1
DC2 DC 2
DC4 DC 4
DC19 DC 19
CMD DS 1
ILEN DS 1
FG DC 'F'
FB DC 'B'
FA DC 'A'
PG1 DC 1
PG2 DC 2
;初期設定
;0〜19番地を0クリアし、割込みベクトル等をセット
:
;コマンド処理
;>プロンプトを出して指示を待つ。
;fならPR1だけを走らせ(RUNにPR1を入れ、READY,WAITを空にしてPMANへ)、
;bならPR1とPR2を同時に走らす(RUNにPR1,READYにPR2,WAITを空にしてPMANへ)
CMDP OUT PPT,DC1;プロンプト表示
:
FGD LD GR0,PG1
:
JUMP PMAN
BGD LD GR0,PG2
:
JUMP PMAN
ALL LD GR0,PG1
:
JUMP PMAN
;PMANプロセス管理
;RUNにPG1が入っていればPR1を走らせ、PR2が入っていればPR2を走らす。
PMAN LD GR0,DC1
:
STAPG1 LD GR4,P1GR4
:
LPSW P1SA
STAPG2 LD GR4,P2GR4
:
LPSW P2SA
IDL IDLE
;IO割り込み
;PSWはOPSWに退避されてここに来るので、OPSW、GR4,5をPG2領域に退避し、
;(割り込まれるのはPR2)、RUN(PR2)をREADYに入れ、
;WAIT(PG1)をRUNに入れ、WAITを空にし、PMAN(プロセス管理)へ
IOI LD GR0,DC0;RUNプロセス無いならIDLWへ
:
JUMP PMAN
;SystemCallIN(SCIN)
;PSWはOPSWに退避されてここにくるので、OPSWをPG1領域に退避し
;(これを出すのは今回PR1のみ)、READY(PG2)をRUNに入れ、READYを空にし、
;WAITにPG1を入れ、SIOを出してINスレッドを走らせ、PMAN(プロセス管理へ)
SCIN LD GR0,OPSW
:
SIO
JUMP PMAN
;ユーザプログラム1:一文字読んでは1文字書き出すことを繰り返す
USRPR1 OUT PAS3,DC4
READ U1DA,U1LEN
OUT U1DA,U1LEN
JUMP USRPR1
U1INC DC 'INPUT'
U1LEN DS 1
U1DA DS 3
;ユーザプログラム2:LD,STを繰り返す
USRPR2 LD GR4,U2DC1
ST GR4,U2DA
JUMP USRPR2
U2DC1 DC 1
U2DA DS 1
END
付録(MICROSのためのエミュレータ修正備忘録、古谷用)
(1) READ:第一オペランドをGR6、第二オペランドをGR7に入れてSVC6を出す。
SVC6では、3番地(SCINT)に1を立てる。
(入力はINスレッドで実行される)
(2) WAIT:2番地が0でない時WAIT命令を繰り返し実行。
(3) LPSWは間接JUMPとして実現。
(4) 命令フェッチ前の割込み処理は、
1番地と3番地をチェックし、OSモードにする。
(5) IDLE処理:PMANでRUNに何もない時、IDLEを呼ぶ。IO割込みでは、まずRUNプロセスが有るかを調べ、有れば状態退避、無ければ退避せず。
(6) IN,OUTはCASL2本来のIO。
(7) INX,OUTXはIOのスレッド実行。スレッドではGR6を入力データの格納場所、GR7を入力文字数の格納場所に使用。
(8) INスレッド内でIOSTSを1にしていたが、INXの場合INXの前でIOSTSに1を入れ、INXの後でWAITを出さないと入力を待たずに抜けちゃう。