OSECPUの仮想CPUのアーキテクチャ
- (by K, 2012.09.11)
- [注意]この内容は古い内容を含んでいるので読み飛ばしてください!
ビット数
- 32bitとする。
- 厳密には1bitから256bitまでの可変アーキテクチャなのだが、それをフルサポートするのは第三世代OSASKとし、OSECPUではその中の32bitモードのみをサポートする。簡略化のためである。
レジスタ
- 16本の整数レジスタ(符号付き整数のみサポート): R00~R0F
- 16本のポインタレジスタ:P00~P0F
- P00はプログラムカウンタ(EIP)
- ポインタのビット数はOSに依存する。
- 浮動小数点レジスタなどは第三世代OSASKでは計画されているが、OSECPUでは未定。
セキュア対策(レジスタ編)
- 整数レジスタ同士の演算については特に制限はない。普通のCPUにできることはできる。
- ポインタレジスタへの演算はきわめて制限される。
- まずポインタレジスタにはすべて型情報があり、演算時にチェックを受ける。 int * を char * にキャストするみたいなことは許されない。配列をはみ出すような演算もできない。
- 整数レジスタは配列の添え字指定には使えるが、メモリアドレスの指定には使えない。逆にポインタレジスタはメモリアドレスの指定にしか使えない。配列の添え字指定には使えない。
- ポインタ型が同型で、かつ共に同じ配列の一部の時だけ、ポインタ同士の引き算ができて、その結果は整数レジスタで受ける。
- 整数レジスタとポインタレジスタの間でMOVすることはできない。
- ポインタレジスタの値を定数と比較することはできないので、NULLかどうかを判定するには、OSから教えてもらったNULLポインタ値と比較するしかない。
- OSにはNULLポインタを教えてくれるAPIがある。
- つまりポインタレジスタの値を何らかの整数に変換する方法はない。表示もままならない。それはOSに頼むしかない。
- もちろんポインタレジスタに何か狙った値を入れることもできない。
セキュア対策(メモリ編)
- アプリがmallocするとき、必ずOSに型情報を申告しなければいけない。そして申請時と違うメモリの使い方はどうやってもできない。違う使い方がしたいのなら、一度そのメモリをOSに返却して、使いたい型でまたメモリをもらってくるしかない。
- 返却域をさすポインタをレジスタとメモリ上からきれいに消せば、返却されたメモリを他の用途で再利用しても安全だなあ。そうでないと、unionみたいになる危険がある。
- union型を許さない。
- ポインタ型の変数に書き込めるのは、ポインタレジスタの値だけである。整数レジスタで書き込むことはできない。逆もできない。書くことだけではなく、読むのもできない。
- このような仕組みのため、OSは全てのメモリの使われ方を十分に把握できる。あるメモリ上の1バイトを取り出したとき、これが char なのか int の一部なのかポインタの一部なのか、ちゃんと識別できている。
RISC的なところ
- 演算はレジスタ間でしかできない。定数やメモリオペランドが指定できるのは、ロードとストアのときだけである。
- フラグレジスタを持たない。CMP系の命令が3項演算になっていて、指定された大小関係が成立したら、結果を収めるレジスタに-1が代入される。成立してなかったら0が代入される。
- JMP命令などはなく、単にP00への代入によって分岐する。
- 条件分岐命令はなく、P00への代入命令の直前に条件実行プリフィクスをつけることで実現する。
- 条件実行プリフィクスは任意の命令につけられるので、これによって条件MOVなどもできる。
こめんと欄
- このページにこめんと欄はありません。このページの内容にコメントしたいときはimpressionsにお願いします。