ページへ戻る

− Links

 印刷 

GUIGUI01​/memo01 のバックアップソース(No.3) :: OSASK計画

osaskwiki:GUIGUI01/memo01 のバックアップソース(No.3)

« Prev[4]  Next »[5]
* ぐいぐい01に関するメモ-01
-(by [[K]], 2008.04.25)
-メモのうち重要な部分をそのうちまとめてまともなページを作る
*** (5) KHBIOSとの関係
-何かにつけて「ぐいぐい01」はKHBIOSの影響で改良に成功とか言っている気がするので、少し詳しく説明しておく。他の人から見たら、「ぐいぐい01」がKHBIOSの影響を受けているのはちっとも自明ではない気がするので。
-「ぐいぐい00」では、第一にIA-32にとって最良のAPIとは何かから出発して設計していた。まあこれで本当にIA-32にとって最良の設計に到達できていれば何も問題はなかったのだが、実際はそうではなかった(今になって思えば)。
-KHBIOSを作るにあたり、KHBIOSはIA-32のみならず、どんなCPUにとっても合理的な設計でありたいと強く思った。これはKHBIOSが一つのディスクでAT/TOWNS/PC98のどれでも起動できるような仕様にしたいと思ったのに関連して、PowerPCのMacやそのほかのアーキテクチャのコンピュータも意識し始めて、それで特定のCPUのみならず、過去現在未来のアーキテクチャまで含めてベストを目指そうと、より深いレベルから設計を考えた。
-そうして目が肥えてくると、「ぐいぐい00」を見たときに、なんとまあ今までいい加減なレベルで満足していたんだと思うくらいに問題点が出てきた。それで、KHBIOSの設計を反映させてAPIを作り直したのである。
*** (6) APIの基本構造(1)
-(ここの話はアセンブラでギチギチに最適化されたアプリを読み書きするときしか必要ない知識で、introシリーズ感覚でCでプログラムするときはこんなことを全く理解していなくて問題ない)
-「ぐいぐい00」では基本のデータ型は32bitの整数であった。これに対し「ぐいぐい01」の基本のデータ型はない。ただよく出てくるデータ型というのはある、それは4bit整数である。もちろんすべての数値を4bitで表せるなんて事はめったにないので、4bitで表せない数値は2倍長の8bitや3倍長の12bit、もちろんそれより長い16、20、24、28・・・といくらでも伸ばせる。多倍長の場合、エンディアンはビッグである。インテルでおなじみのリトルではない。これらは何ヶ月(というか1年以上?)どうするのが一番いいのかを考えた末の[[K]]なりの結論である。
-4bitで数値を表すといっても、0~15の符号なし整数が扱えると思いきやそうではない。実際は4bitでは0~7までしか表現できない。というのは、最上位ビットがヘッダで、「これは4bit形式ですよ」ということを示しているからである。8bit形式の場合は3bitがヘッダ、12bitも16bit形式も3bitがヘッダ、20bit形式では6bitもヘッダに食われる。
-かつては多倍長形式といえばs7sのような「継続ビット系」の設計をよく使っていたが、これはあまりよくないと今では思っている。というのは数値をデコードする際にエンコード長を早く抽出できたほうがデコードはやりやすいわけで(たとえばFPGAなどでデコードすることを考えている)、それならエンコード長を得るためのデータは一箇所にまとまっているほうが有利だからである。
-実際のエンコードは次の通り(右は二進数):
--4bit形式(0~7): 0xxx
--8bit形式(0~31): 100xxxxx
--12bit形式(0~511): 101xxxxxxxxx
--16bit形式(0~8191): 110xxxxxxxxxxxxx
--20bit形式(0~16383): 111000xxxxxxxxxxxxxx
--24bit形式(0~262143): 111001xxxxxxxxxxxxxxxxxx
--28bit形式(0~4194303): 111010xxx...xxx (xは22bit分)
--32bit形式(0~67108863): 111011xxx...xxx (xは26bit分)
--36bit形式(0~1073741823): 111100xxx...xxx (xは30bit分)
--40bit形式(0~17179869183): 111101xxx...xxx (xは34bit分)
--以下この調子でどこまでも
-ここまでで説明したエンコード法を以後eh4と呼ぶことにする。
-----
-「ぐいぐい01」ではすべての数値をeh4で書かなければいけないというわけではない。ヘッダなど持たず、しかもリトルエンディアンな、つまりIA-32にとって扱いやすいnビット整数もある。たとえば8bit、16bit、32bit、64bitなど。もちろんこれを半端にして、6bitだったり、13bitだったりしてもいい。これらはAPIデータ列内でフォーマット変更ファンクションを使うことで、何度でも変更できる。この数値はeh4、次の数値は普通の16bit、次の数値は普通の64bit、みたいにできるというわけである(nビット整数形式ではエンディアンはそのアーキテクチャにとって自然なものを使う)。
-このようなことを許した代償としてOS内(efg01内)のAPIのパラメータのデコードルーチンがやや複雑になってしまっている。とても単純だった「ぐいぐい00」の頃とは大違いだ。しかし逆にこれによって柔軟性や汎用性は大いに高まっている。
-たとえば「ぐいぐい00」ではポインタといえばすべて32bitか48bitであって、もしx86-64なOSASKが登場したらこれらを見直してAPIのフォーマットを再設計しなければいけない。また「ぐいぐい00」ではグラフィックの座標は32bitで十分に表現できると想定しているが、もしかしたら32bitでは足りなくなる時代がいつか来るかもしれない(ええ!、くるのか?)。そうなったらまたAPIを変更するか増やすかしなければいけない。特に歴史の長いwin32を見ているとパラメータ長などの変更によって生まれた似たり寄ったりのファンクションが結構ある。これはAPI全体を冗長で非効率なものにしてしまっている。
-しかし「ぐいぐい01」ではパラメータを可変長にしてあるので、こういう問題は生じない。またもし16bit環境用にAPIを用意することになっても、それはそういう短い形式を多用すればいいだけだ。またたとえ32bitや64bit環境でも必要のないゼロ拡張をしなくて済む(たとえばこのファイルは明らかにファイルサイズが16bit以内で表せると分かっているのに、わざわざ64bitで表現しなくてもいい、グラフィックのボックスのサイズが1024x128なのでこれを超える座標を指定することはありえないのに、わざわざ32bitにしなくても済むということ)。これらはアプリを小さく書けることに貢献している。
-またフォーマット変更ファンクションを最初に一度だけ使って32bitの整数モードにしてしまえば、後は「ぐいぐい00」感覚で使うことも可能である。これによりアプリのサイズで「ぐいぐい00」よりも悪くなるケースはほぼないと思われる。
*** (7) APIの基本構造(2)
-(ここの話はアセンブラでギチギチに最適化されたアプリを読み書きするときしか必要ない知識で、introシリーズ感覚でCでプログラムするときはこんなことを全く理解していなくて問題ない)
-「ぐいぐい01」のAPIデータ列の仕様は、「ぐいぐい00」の頃のような単純に数値として意味のあるものと数値のエンコード法を記述する部分との混在になっている。たとえば以下はhellok0.g01内で実際に使われているAPI列である。
 35 01 24 8D 68 65 6C 6C 6F 2C 20 77 6F 72 6C 64 0A 44 03
-これを分解しつつマークをつけるとこうなる。
 (3) 5 0 (1) (2 4) [8D] 68 65 6C 6C 6F 2C 20 77 6F 72 6C 64 0A (4) 4 0 3
--(x)は純粋にエンコード法を記述するためのもの(基本的にeh4)
--[x]は基本的にはエンコード法の記述だが、データとしても意味のあるもの(基本的にeh4)
-必ず最初は(x)で始まる。最初の(3)はデフォルトのエンコード法(ここではeh4)のまま、有効なデータが2個継続するということを表す。この2という数字は、3-1で求めた。
-そして、5と0という数値が来る。これは純粋なAPIファンクションのデータで、詳細は「(8) APIの基本構造(3)」で説明する。
-そして5と0を読み終わったことで、先の指定による「2個」が切れたので、再び(x)が来ることが予想される。ということで1つeh4でデコードすると、(1)だった。1-1=0なので0個のデータが継続するといいたいところだが、0個というのは意味不明であって、ここではエンコード法の変更を意味している。
--ちなみに(0)を指定した場合は、0-1=-1で-1個のデータが継続するというさらに不可解なことになるが、これは単なるNOPである。
-次の(2 4)は、2が「一時的なエンコード法の変更で、以降は符号なしで、かつ後続する継続データ数そのものもデータとして扱う」を意味し、その後ろの4が、2^(4-1)=8で、符号なし8bitエンコードモードであることを表している。
--一時的というのは、この符号なし8bitが終わったら、またもとのeh4に戻るという意味で、これを永続的にしていると、以後は符号なし8bitがデフォルトになり継続する。
--2のベキではない長さのデータ長を指定する方法はまた別の機会に。
--2^(0-1)のときはeh4を意味する。
-次の8Dはeh4で0xd=13を意味するが、この13はAPIのデータでもあるし、符号なし8bitのエンコードが続く長さでもある。
-(4)は4-1=3で3個のデータが継続するという意味になる。
----
-同様にchars0.g01も分解してみる。
 06 50 1A ?? 30 00 00 00
-これも同様にマークをつけるとこうなる。
 (0) (6) 5 0 1 A?? 3 (0)...
-最初の(0)はNOPで、主にパディングのために入れている。
-chars0.g01は最後にもう一つAPIを呼んでいる部分がある。
 55 01 8A 44 03
-これはこうなる。
 (5) 5 0 1 8A (4) 4 0 3
*** (8) APIの基本構造(3)
-(ここの話はアセンブラでギチギチに最適化されたアプリを読み書きするときしか必要ない知識で、introシリーズ感覚でCでプログラムするときはこんなことを全く理解していなくて問題ない)
-以後はフォーマット指定はすべて無視して読むこと。
----
-ファンクション番号:0 -- NOP
--パラメータはない。何もしない。
-ファンクション番号:3 -- 終端ファンクション
--パラメータはない。APIの呼び出し処理を終わる。
-ファンクション番号:4 -- 終了ファンクション
--通常はパラメータが1つ継続する。パラメータ0を指定すると通常の正常終了を意味する。通常の正常終了においては、親タスクに正常終了を知らせつつ、オープンになっているslotはすべて閉じられ、本タスクは破棄され、タスクディレクトリ(ようするにスタックのイメージなど)も削除されるのがデフォルト動作である。
-ファンクション番号:5 -- データ列出力ファンクション
--slot番号、データ数、データ列が継続する。とりあえず、バイト数と文字列だと思っておけば今のところは問題ない。slot番号0はデフォルトコンソールであり、データはIBMのUS仕様半角キャラクタコード列だと認識され、いくつかの制御コードも有効である(これらは設定によって変えられる)。・・・これが単なる「標準出力への出力」にとどまらないあたりが、仮想化重視の「ぐいぐい01」である。
-(つづく)

* こめんと欄
#comment

« Prev[4]  Next »[5]