|
1: 2008-12-23 (火) 14:24:11 |
| + | * ぐいぐい01に関するメモ-15 |
| + | -(by [[K]], 2008.12.23) |
| + | -メモのうち重要な部分をそのうちまとめてまともなページを作る |
| + | *** (30) helloの改良の歴史 (118→18) |
| + | -(参考として)DOS |
| + | --22バイトが限界 |
| + | --ヘッダとかはない。AHとDXに代入してINT21H。終了はRETでいい。 |
| + | [レジスタ代入5バイト] [API-callに2バイト] [RET] [文字列13バイト+ターミネータ1バイト] |
| + | -旧OSASK初期風: |
| + | --118バイトくらいが限界(非圧縮時) |
| + | [計18バイトのシグネチャやワークエリア設定など] [API-callに標準で7バイト] |
| + | [FS:EBXの設定に最低5バイト] [APIパケットは全部32bit固定なので、初期化func- |
| + | ofs-表示func-opt-dev-len-(13文字)-終了func-opt-パケット終了funcで88バイト] |
| + | -旧OSASK後期風: |
| + | --optの指定でキャラクタコードは8bitでも記述できるようになる。 |
| + | --82バイトくらいが限界 |
| + | [計18バイトのシグネチャやワークエリア設定など] [API-callに標準で7バイト] |
| + | [FS:EBXの設定に最低5バイト] [APIパケットは全部32bit固定なので、初期化func- |
| + | ofs-表示func-opt-dev-len-(13文字)-終了func-opt-パケット終了funcで52バイト] |
| + | --当時は(といっても結構長い期間)この程度で喜んでいた。 |
| + | -(参考として)「はりぼてOS」 |
| + | --読者への説明のしやすさを重視しDOS風のAPIを採用(INT40H)。EDXにfunc番号、EBXにC文字列。 |
| + | --52バイトが限界 |
| + | [ヘッダ27バイト] [EBP=ESP PUSH(2) POP(EDX) INT40H DL=4 INT40H で11バイト] |
| + | ["hello, world\n\0"で14バイト] |
| + | --OSASKと比べて30バイトものアドバンテージ!いいのか!? |
| + | --しかしAPI-callをタスクローカルにできないINTにはしたくないし、パケットAPIも好きなので変えたくない。 |
| + | -27バイトのhello |
| + | --DOS版が22バイトなのは16bitだからしょうがないと思えたが、「はりぼてOS」に負けたのは屈辱的だった。そこで設計をやり直す。 |
| + | --適当な標準値を設けてそれを変更する方式で、スタックサイズなどを記述させることに。標準値は小規模プログラムには十分な値なので、helloでは変更の必要全くなし。 |
| + | --またパケットを32bit固定からeh4という4bit単位可変長エンコードに変更(のちにgh4にアップグレードするがhelloは影響なし)。小さい数値なら4bitで収まるので、パケット効率8倍に! |
| + | --またレジスタ初期値を工夫しEBPの値を破壊しない限り、CALL(EBP)の2バイトでAPI-callができるようになった(EBXを変更しなければEIPからパケットが始まると見なされる)。終了もDOSと同じくRETだけでもOKに。初期化funcはシステムが事前に適当にやってくれるので、それを変更したいとき以外は省略可能。 |
| + | --シグネチャを2バイトに。 |
| + | --これで27バイト |
| + | ['G' 01 で2バイト] [セクション記述用4バイト] [CALL(EBP)で2バイト] |
| + | [5 0 13 "hello, world\n" 4 0 3 の内容で16.5バイト、パケットのフォーマット制御で2バイト] |
| + | --5は表示func(次の0はdev、フォーマット制御をしなくてよくなったので表示funcのoptは廃止)、4は終了func、3はパケット終端func |
| + | --「はりぼてOS」版よりもはるかに小さくなったこともあり、この結果に大満足。 |
| + | -22バイトのhello |
| + | --そしてCOM64plusが登場。シグネチャを小さくしてレジスタ初期値などのテクニックやスタックサイズ標準値のような手法を導入した結果、hello記述力が21バイト!これに負けたくないと、仕様改良を断行。 |
| + | --まず.g01アプリには.textセクションしかない上にリロケーションも必要ない場合が少なくないと分かってきていたので(それらがなくても新APIの記述力のおかげで十分いろいろできる)、ファイル末端までを.textセクションイメージと見なすセクション記述法を導入。これは従来の拡張なので問題はない。これで[セクション記述]は1バイトでよくなった。似たような簡易セクション記述モードの導入はCOM64plusでも既にやっていた(というか僕がそうしたらどうかと提案した、その結果が21バイト)。 |
| + | ---こういう特別モードについては当初心理的な抵抗があった。小さいプログラム向けに特別な形式を用意するのなら、それは有利になるに決まっている。あくまでも汎用的な方法だけなのにこんなに小さくなる、ということこそ僕の美学だった。 |
| + | ---しかし将来他のOSとのアプリサイズ競争になったときに、この美学のために小プログラムで全敗することになれば、他の評価すべき特徴と一緒に全部まとめて、「あれはだめだ、あれはうまくいかない、あれは負けたから」と評される心配がある。ここはやはり多くのケースで役立つのなら、積極的に導入するべきだと決断。 |
| + | --アプリ終了時に最後に表示した文字が'\n'ではない場合に'\n'を自動出力するモードを設けた(1バイトのセクション記述子内のフラグでこのモードの利用の有無を設定できる)。これで'\n'の出力を省略(これもCOM64plusでやっていた、僕の提案)。 |
| + | --.textセクションは多くの場合最後がRETになっているという性質を発見。それならリンカで末尾のRETを勝手に省いて出力し、ロード時に付加すればいいじゃないかと思った。もちろん稀に末尾がRETになっていないこともあるが、その場合もRETが勝手に付加されて特に困ることはない(これもCOM64plusでやっていた、僕の提案)。 |
| + | --これで22バイト |
| + | ['G' 01 で2バイト] [セクション記述用1バイト] [CALL(EBP)で2バイト] |
| + | [5 0 12 "hello, world" 3 の内容で14.5バイト、パケットのフォーマット制御で2バイト] |
| + | * こめんと欄 |
| + | #comment |