バージョン番号表記
好きだねぇ~これwww
すこし調べてみると、.g01アプリの場合、ソース冒頭で引数の定義を行っている。で、それに対応して自動的にUsage表示をしてくれると。こういう仕組みになってた。
今までは普通のCのソースに文字列を書き足せばそれでよかった。
(もちろん.g01だってそれは出来る。)
・・・でもなぁ。なーんかそれじゃ、色気がないというか。欲が出てきた。
そこで、Usageと同じように、ソースヘッドに番号だけを埋め込んで、hijk側で制御するようにできないもんかなぁと。いかにもefg01の仕様っぽいし、サイズだって極限まで絞れ、無駄が出ないようにできるはず。(なにより、そういう統一的な形のほうがなんかカッコよくない??)
で、現在の妄想。バージョン番号を出したい場合はhijk側でオプションを付けるってのはどうだろう?
>hijk.exe -v Nasuka.g01 hijk Version 1.1 Nasuka Version 1.3 Usage>Nasuka in:filename out:filename
こんな感じに。
この構想には二つ意味がある。まず、現在はなにも引数をつけないと自動的にUsageが表示されるという仕様になっているんだけど、なにも引数をつけない場合はディフォルトの設定で動作を始めてほしいというアプリだってあるはずだ。(引数自体は持っている)そういう設計のアプリの場合、今のUsageの仕様はすこし不便ではないかと考えた。また当然、バージョン番号等を統一的に扱うような仕様にしておけば、小さくなるばかりではなく、説明や使い方を書く場合も最低限の文章で書くことができるはず。
- なぜそんなにバージョン番号を付けたがる!貴様それでも軍人か!!!
- 民間人です。はいwww
- 好きだから
- オイラ自身がいろんなツールを収集・整理する時に、バージョン番号がないものを調べる時に猛烈に苦労したから。どれが新しいのか古いのか。新しくたっていいとは限らない。新たなバグが入り込んでいる場合だってある。ファイルの日付なんてアテにならないし、コンパイラが変われば出てくるバイナリが変化することだってあるわけだし。
バージョン番号の文字列の制限
これはUsage(オプションの扱い)でも同じで、普通のC言語のように自由気ままにやらせちゃうと余計な容量やコードが入り込み、さらには非統一的にもなる。あえて出来ることを絞ることでこの問題は解消される。
誤解してほしくないのだが別にそれを悪だと言ってるんじゃないよ。ヘンな突っ込み入れんといてね。
たとえばこんな仕様。
- バージョン番号はあくまでも番号なので、数値のみで行う
- 3つだけってことにする。(6.3.2とか)三つまでを許容しておけば、日付タイプにも対応できる(10/12/03版とか)
- 各番号は256まで。(実際、バージョン189とかってなさそうだし、落とし所ではないかと)
- どうしても番号以外の場合は別にコードを打ち込むような仕様にする
どかな??
できるかな?
ここでいろいろ解析してみた。0x0cとか0x1cとかのコードを打ち込むことで、タイプや文字数を指摘している仕様らしい。
なんか余ってないかな? さっそくソースコードを読み解いてみる・・・
ここかなぁ・・・ func06_init();
void func06_init() { UCHAR *p; func06str = malloc(sizeof (struct FUNC06STR)); func06str->flags &= 0; func06str->usgs = 2; func06str->def_arg0 = 1; func06str->usg[0].tag[0] = '\0'; func06str->usg[0].flg = 0; func06str->usg[0].usg[0] = '\0'; func06str->usg[0].typ = 0xff; func06str->usg[1].tag[0] = '\0'; func06str->usg[1].flg = 3; func06str->usg[1].usg[0] = '\0'; func06str->usg[1].typ = 0xfe; /* 3:str */ for (func06str->argv0 = p = *main_argv; *p != '\0'; p++) { if (*p == '\\' || *p == '/') func06str->argv0 = p + 1; } return; }
うーん。この関数って、内部にコマンドライン情報を格納するための構造体を定義して、さらに初期化してる・・・のかなぁ???
102行目がそれかな。ここでFUNC06STR構造体を定義。さらに108行でそれをグローバル変数として生成・・・かなこれ?
おっと!FUNC06STR内に、さらにFUNC06STR_SUB00構造体が入ってる。入れ子になってるのか
FUNC06STR構造体
0 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
1 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
2 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
・ | |||||||||
62 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
63 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
def_arg0(int×1) | |||||||||
flags(int×1) | |||||||||
usgs(int×1) | |||||||||
*argv0(ポインタ) | |||||||||
argv_f(256文字) | |||||||||
argv_all(6万5千文字) |
- func06_initはなにをやってるのか?(ヘタレの予測)
- メモリをmallocを使って確保(全部でいくつになるんだこれ?掛け算ややこしいのでパスwww
- flagsをゼロに(なんで?)
- usgsを2に(とりあえず、引数は二個だよってことで初期化かな)
- def_arg0を1に(なんだろこれ。defっていうくらいだから、省略時の規定値・・・かな?)
- 以降、とりあえず2列、usg(FUNC06STR_SUB00構造体)に値を当て込んでいる
- tag[0]に0を。(tagは文字列なので、頭に0を入れて空文字ってことにする?)
- flgを0に。(なんだろう。flgかぁ。なにを表すものかな?)
- usg[0]に0を。(同じく空文字化だと思う)
- typを0xffに(0xffはなんだろう?0xfeは文字列引数ってことらしいが・・・)
- 次にforループはなにしてるんだろう? *main_argvって、たぶん与えられた引数(コマンドライン)丸々を格納している変数のポインタだと思うんだけど・・・文字列内に / か \ があったらargv0を一個増やす・・・いや違うなぁ
煮詰まった・・・
ちょっと別の方向からアプローチしてみよう。
gas2naskのソースを見てみると、先頭で例のコマンドラインの設定をして、そのあと、g01_setcmdline関数を呼び出している。この関数はなにをやってくれてるんだろう???
んんん? guigui01.hを見てみると、この関数はdefineになってるなぁ・・・defineって、文字列置換だったよね?たしか???
#define g01_setcmdlin(p) __asm__ __volatile__("movl %%eax,%%edi\n\tcall _g01_execcmd"::"a"(p):"%esi","%edi","cc")
つーことは・・・・
__asm__ __volatile__("movl %%eax,%%edi\n\tcall_g01_execcmd"::"a"(p):"%esi","%edi","cc")
これに置換された後コンパイルされるってこと・・・なのか? なんだべ? これ???
はっはあぁぁぁ・・・・・
わかったぞ! これはgcc由来のインラインアセンブラの書き方だ! 分解して書いてみると・・・
__asm__ __volatile__(" movl %%eax,%%edi call_g01_execcmd"::"a"(p):"%esi","%edi","cc" )
うへぇ! 難しい・・・。 eaxの値をediに写し、g01_execcmdを呼び出している・・・のかな??
やっと見つけた。startup.ask内にやっとこさg01_execcmdを見つけた・・・
だめだあぁぁぁ・・・わっかんねえぇぇぇぇ・・・・
func06_putusage()
この関数を見ていると、やっぱりどう見ても、例のコマンド定義の文字列はfunc06str構造体に格納されているらしい。この構造体は先のinitで初期化されているんだけど、どこでここに定義されたものが当て込まれているんだろう。その部分が解れば、特別なコードを使って「以下はバージョン番号」だよ!と定義できるはずなんだが・・・・
ヒントキターーー!
seroさんがヒントくれた!! さっそくそのへんを検証・・・・すると・・・
こんなコードを発見。状況から予測を当てはめると・・・
for (j = 0;; j++) { ←jは63までループする仕様。(超えるとエラー?) i = getnum_api(&ra, 0); たしか、SUB00構造体もこの数! if (i == 4) { func06str->usgs = j; ←iが4だとループを打ち切る。4? 0x40が終端じゃなかった? break; ブレイク時にその数をusgsに記憶?引数の個数になるぞ?! } if (j == 64) { puts("func6: internal error (2)"); exit(1); } if (i == 5) i = 0xfff0 << 2 | 0; if (i == 6) ←引数の先頭の決め打ちコードは0x86・・・ i = 0xfff1 << 2 | 2; if (i == 7) { ←確か、改行コードは0x87・・・7!? /* 改行 */ if (j == 0) { ←jが0の時。引数の先頭?に改行がある状態? エラーにしてる puts("func6: internal error (3)"); exit(1);
まだ確認が甘いが、このiって、コードの一桁目に合致するような気がしてならない・・・
そもそもiってなんだよ? i = getnum_api(&ra, 0); getnum_apiってのはどういう関数だ???
また、一桁目が重要なのは、いずれも0x8xなコード達。(他のは逆に、一桁目が可変するものが多い)
- なぜ0x8xが選ばれてるんだろう? ヤマカンでASCIIコード表をみてみると。これクサイぞ???
- 俗に言われるASCIIコードのうち、0x80以降は第7ビットが立っている。これを境に、前・後とわけることができる。
- キーボードから入力できる文字はみな前半に意図的に集中されている。つまり、コードの第7ビットを摘出するだけで容易に文字なのかコードなのかを判断できる
i = 0xfff0 << 2 | 0; ←なにしてっかってーと・・・ ・ 1111111111110000(0xfff0) を左に二つ、ビットシフトしなされ。 ・ 1111111111000000 できやした。 ・ 0000000000000000(0) ゼロと論理演算(論理和)しなされ ・ 1111111111000000 できやした~ あれ?? これ、なにをしてるの??なんのためにこんな演算を???
一般用コメント一覧
- seroです。こないだg01アプリ作るときに、オプションの名前だけでなく、説明のほうも文字数から1を引いてしまうというミスをしでかしてエラーになったことがありまして、そのときのefg01解析からヒントになる部分を。 とりあえず、アプリのg01_execcmdコールの行き先は最終的にefg01のc_apiですよ、ってのが一点目。 二点目は、その中の、for(;;).if(i==6).if(test_sig4).if(func06str)節あたりでオプション指定の解析やってるようです、ってこと。 時間なくて殴り書きですみません。時間あったらページ作って解説やりたいところなんですが…… -- ◆sero 2010/2/1 22:45
Counter: 343,
today: 1,
yesterday: 3
初版日時: 2010-01-31 (日) 12:51:19
最終更新: 2010-02-02 (火) 00:00:00 (JST) (319d) by lina
|
ぺージ情報 | 閲覧可 | 編集可 | |||
---|---|---|---|---|---|---|
ぺージ名 : | hideyosi/hijk計画 | グループ : | すべての訪問者 | グループ : | 登録ユーザ | |
ページ作成 : | lina | ユーザー : | すべての訪問者 | ユーザー : | なし | |
ページ別名 : | 未設定 |