2: 2010-01-31 (日) 15:35:39 lina |
現: 2024-01-08 (月) 12:58:58 lina |
| | | |
| >hijk.exe -v Nasuka.g01 | | >hijk.exe -v Nasuka.g01 |
| + | |
| hijk Version 1.1 | | hijk Version 1.1 |
| Nasuka Version 1.3 | | Nasuka Version 1.3 |
| | | |
| こんな感じに。 | | こんな感じに。 |
| + | |
| + | COLOR(blue){この構想には二つ意味がある。まず、現在はなにも引数をつけないと自動的にUsageが表示されるという仕様になっているんだけど、''なにも引数をつけない場合はディフォルトの設定で動作を始めてほしい''というアプリだってあるはずだ。(引数自体は持っている)そういう設計のアプリの場合、今のUsageの仕様はすこし不便ではないかと考えた。また当然、バージョン番号等を統一的に扱うような仕様にしておけば、小さくなるばかりではなく、説明や使い方を書く場合も最低限の文章で書くことができるはず。} |
| + | |
| + | -なぜそんなにバージョン番号を付けたがる!貴様それでも軍人か!!! |
| + | --民間人です。はいwww |
| + | --好きだから |
| + | --オイラ自身がいろんなツールを収集・整理する時に、バージョン番号がないものを調べる時に猛烈に苦労したから。どれが新しいのか古いのか。新しくたっていいとは限らない。新たなバグが入り込んでいる場合だってある。ファイルの日付なんてアテにならないし、コンパイラが変われば出てくるバイナリが変化することだってあるわけだし。 |
| | | |
| **バージョン番号の文字列の制限 [#o541cb97] | | **バージョン番号の文字列の制限 [#o541cb97] |
| | | |
| なんか余ってないかな? さっそくソースコードを読み解いてみる・・・ | | なんか余ってないかな? さっそくソースコードを読み解いてみる・・・ |
| + | |
| + | ここかなぁ・・・ 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行でそれをグローバル変数として生成・・・かなこれ?~ |
| + | COLOR(blue){おっと!FUNC06STR内に、さらにFUNC06STR_SUB00構造体が入ってる。入れ子になってるのか} |
| + | |
| + | ***FUNC06STR構造体 [#u5ca8f2e] |
| + | |
| + | |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)| |
| + | |>|>|>|>|>|>|>|>|>|CENTER: ・ | |
| + | |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)| |
| + | |>|>|>|>|>|>|>|>|>|LEFT:def_arg0(int×1)| |
| + | |>|>|>|>|>|>|>|>|>|LEFT:flags(int×1)| |
| + | |>|>|>|>|>|>|>|>|>|LEFT:usgs(int×1)| |
| + | |>|>|>|>|>|>|>|>|>|LEFT:*argv0(ポインタ)| |
| + | |>|>|>|>|>|>|>|>|>|LEFT:argv_f(256文字)| |
| + | |>|>|>|>|>|>|>|>|>|LEFT: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を一個増やす・・・いや違うなぁ |
| + | |
| + | |
| + | ***煮詰まった・・・ [#s5ca9fbc] |
| + | ちょっと別の方向からアプローチしてみよう。 |
| + | |
| + | 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() [#g9fc44c1] |
| + | この関数を見ていると、やっぱりどう見ても、例のコマンド定義の文字列はfunc06str構造体に格納されているらしい。この構造体は先のinitで初期化されているんだけど、どこでここに定義されたものが当て込まれているんだろう。その部分が解れば、特別なコードを使って「以下はバージョン番号」だよ!と定義できるはずなんだが・・・・ |
| + | |
| + | *ヒントキターーー! [#i6061478] |
| + | 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 できやした~ |
| + | |
| + | あれ?? これ、なにをしてるの??なんのためにこんな演算を??? |