3: 2008-12-23 (火) 23:01:36 |
現: 2024-01-08 (月) 12:58:42 k-tan |
- | * ぐいぐい01に関するメモ-16 | + | TITLE:x |
| + | * ぐいぐい01に関するメモ-16 [#d0062872] |
| -(by [[K]], 2008.12.23) | | -(by [[K]], 2008.12.23) |
| -メモのうち重要な部分をそのうちまとめてまともなページを作る | | -メモのうち重要な部分をそのうちまとめてまともなページを作る |
- | *** (31) abcdw007のAPIパケットの特徴 | + | *** (31) abcdw007のAPIパケットの特徴 [#d9dfeabb] |
| -マニュアル風に書いたらきっとmanの方になるような内容だけど、どちらかというと面白おかしく書くので、memoに書くことにしました。 | | -マニュアル風に書いたらきっとmanの方になるような内容だけど、どちらかというと面白おかしく書くので、memoに書くことにしました。 |
| -アセンブラレベルでこそabcdw007の仕様のよさがはっきりするので、それを書きたいと思います。 | | -アセンブラレベルでこそabcdw007の仕様のよさがはっきりするので、それを書きたいと思います。 |
| -返したい数字はもっと大きいかもしれません。たとえばexit(100);がやりたければ、 | | -返したい数字はもっと大きいかもしれません。たとえばexit(100);がやりたければ、 |
| EDI = 0; CALL([ESI]); DB(0x43, 0xc6, 0x40); | | EDI = 0; CALL([ESI]); DB(0x43, 0xc6, 0x40); |
- | -とします。パケットは[4 3 100]です。 | + | -とします。パケットは[4 3 100]です(100は0x64なのでgh4ではc64になる)。 |
| -さてこれで定数を終了コードとして返すことは簡単にできました。しかしEAXに入っている値を返したいなんていう場合はどうすればいいでしょうか。旧OSASKなら | | -さてこれで定数を終了コードとして返すことは簡単にできました。しかしEAXに入っている値を返したいなんていう場合はどうすればいいでしょうか。旧OSASKなら |
| PUSH(EAX); PUSH(3); PUSH(4); EBX = ESP; CALL(0xc7,0); | | PUSH(EAX); PUSH(3); PUSH(4); EBX = ESP; CALL(0xc7,0); |
| EDI = 0; CALL([ESI]); DB(0x50, 0x53, 0xb2, 0xb4, 0xb6, 0x30); | | EDI = 0; CALL([ESI]); DB(0x50, 0x53, 0xb2, 0xb4, 0xb6, 0x30); |
| -このパケットは普通に見れば[5 0 5 3 0x32 0x34 0x36 3]となります。しかし0x32は'2'のキャラクターコードなので、ここではあえて[5 0 5 3 "246" 3]と書くことにします。またこの3番目の5はこの文脈では!5という意味で、結果として何の意味も持たないので、これを消すことにします(詳細は後で説明します)。そうすると、結局[5 0 3 "246"][3]となります。パケットはコマンドの切れ目で切ると見やすいのでこう書いています。 | | -このパケットは普通に見れば[5 0 5 3 0x32 0x34 0x36 3]となります。しかし0x32は'2'のキャラクターコードなので、ここではあえて[5 0 5 3 "246" 3]と書くことにします。またこの3番目の5はこの文脈では!5という意味で、結果として何の意味も持たないので、これを消すことにします(詳細は後で説明します)。そうすると、結局[5 0 3 "246"][3]となります。パケットはコマンドの切れ目で切ると見やすいのでこう書いています。 |
- | -これは旧OSASKのパケットととてもよく似ていて(数値はいろいろ違いますが)、slot0で文字数3で文字コードが並んでいるだけなのです。[3]はパケット終端です。これを実行するとアプリに戻ります。 | + | -これは旧OSASKのパケットととてもよく似ていて(数値はいろいろ違いますが)、slot=0で文字数=3で文字コードが並んでいるだけなのです。[3]はパケット終端です。これを実行するとアプリに戻ります。 |
| -これを応用すれば、まずEAX一文字を表示するputcが簡単に作れます。 | | -これを応用すれば、まずEAX一文字を表示するputcが簡単に作れます。 |
| EDI = 0; CALL([ESI]); DB(0x50, 0x51, 0x60, 0x03); | | EDI = 0; CALL([ESI]); DB(0x50, 0x51, 0x60, 0x03); |
| -こんなものです。パケットは[5 0 1 EAX]になります。同じように応用すればhelloももちろん作れます。 | | -こんなものです。パケットは[5 0 1 EAX]になります。同じように応用すればhelloももちろん作れます。 |
| -しかしこのままでは終了ファンクションと同じで大して面白くありません。面白いのはここからです。!5の後に、!6_504_0_!5_1_3_0...と続けることができます。つまりこういうことです。 | | -しかしこのままでは終了ファンクションと同じで大して面白くありません。面白いのはここからです。!5の後に、!6_504_0_!5_1_3_0...と続けることができます。つまりこういうことです。 |
- | EDI = 0; CALL([ESI]); DB(0x50, 0x56, 0xdf, 0x80, 0x51, 0x30, 0x32, 0x34, 0x36, 0x30); | + | EDI = 0; CALL([ESI]); DB(0x50, 0x56, 0xde, 0x80, 0x51, 0x30, 0x32, 0x34, 0x36, 0x30); |
- | -これは[5 0 !6 504 0 1 3 0 "246"][3]という意味になります(余計な!5は消しました)。!6_504_0_1_3というのが特別なもので、!6_504_0は「モード変更直接」次の1が8bit配列モード、次の3が「文字数兼モード長」です。8bit配列モードになれば、数値をいちいちgh4でエンコードしなくていいのです。普通にcharで書けます。ちなみに文字数3の後の0は、ただのパディングですが、これは必ず0でなければいけません。適当な数値を入れると誤動作します。 | + | -これは[5 0 !6 488 0 1 3 0 "246"][3]という意味になります(余計な!5は消しました)。!6_488_0_1_3というのが特別なもので、!6_488_0は「モード変更直接」、次の1が8bit配列モード、次の3が「文字数兼モード長」です。8bit配列モードになれば、数値をいちいちgh4でエンコードしなくていいのです。普通にcharで書けます。ちなみに文字数3の後の0は、ただのパディングですが、これは必ず0でなければいけません。適当な数値を入れると誤動作します。 |
- | -しかし実は、機能番号5のフォーマットは、[5 slot (!6 504) mod (1) len str]となっています(mod=0の場合)。この()で囲まれた部分は、!5で打ち消さなければ自動で挿入される部分です。つまり自動挿入をあてにするなら、 | + | -しかし実は、機能番号5のフォーマットは、[5 slot (!6 488) mod (1) len str]となっています(mod=0の場合)。この()で囲まれた部分は、!5で打ち消さなければ自動で挿入される部分です。つまり自動挿入をあてにするなら、 |
| EDI = 0; CALL([ESI]); DB(0x50, 0x03, 0x32, 0x34, 0x36, 0x30); | | EDI = 0; CALL([ESI]); DB(0x50, 0x03, 0x32, 0x34, 0x36, 0x30); |
| -これで十分なのです。 | | -これで十分なのです。 |
| -また文字列といえば、C言語で見られるような、'\0'で終わるタイプもあります。つまり事前に文字数が分からないけど、ターミネータがあるからたどっていけば終端は分かる、というやつです。そういうのは、mod=1を使うと簡単に扱えます。 | | -また文字列といえば、C言語で見られるような、'\0'で終わるタイプもあります。つまり事前に文字数が分からないけど、ターミネータがあるからたどっていけば終端は分かる、というやつです。そういうのは、mod=1を使うと簡単に扱えます。 |
- | -mod=1のときの機能番号5のフォーマットは、[5 slot (!6 504) mod (1) (term) str]になります。ここでtermはデフォルトでは自動挿入ですが、自動挿入任せにすると0が入ります。まさに'\0'がターミネータですね。 | + | -mod=1のときの機能番号5のフォーマットは、[5 slot (!6 488) mod (1) (term) str]になります。ここでtermはデフォルトでは自動挿入ですが、自動挿入任せにすると0が入ります。まさに'\0'がターミネータですね。 |
| EDI = 0; CALL([ESI]); DB(0x50, 0x10, 0x32, 0x34, 0x36, 0x00, 0x30); | | EDI = 0; CALL([ESI]); DB(0x50, 0x10, 0x32, 0x34, 0x36, 0x00, 0x30); |
| -まだあります。mod=2/3にすると、strの部分が (!6 0) r に化けます(それ以外はmod=0/1と同じ)。これはどういうことかというと、パケットの中に文字列をおかずに、レジスタで指定したところに文字列を置けるのです。これが「モード変更間接」です。 | | -まだあります。mod=2/3にすると、strの部分が (!6 0) r に化けます(それ以外はmod=0/1と同じ)。これはどういうことかというと、パケットの中に文字列をおかずに、レジスタで指定したところに文字列を置けるのです。これが「モード変更間接」です。 |
- | -なんかもう疲れてきたので説明は適当になってきていますが(すみません)、このような(!6 504)の自動挿入は文字列を指定するような場所にはすべて設定されていて、たとえばfopenでファイル名指定するときなんかも、パケットの中にファイル名を埋め込むもよし、ポインタで指定するもよしの、何でもござれです。 | + | -なんかもう疲れてきたので説明は適当になってきていますが(すみません)、このような(!6 488)の自動挿入は文字列を指定するような場所にはすべて設定されていて、たとえばfopenでファイル名指定するときなんかも、パケットの中にファイル名を埋め込むもよし、ポインタで指定するもよしの、何でもござれです。 |
| | | |
- | * こめんと欄 | + | * こめんと欄 [#m17139e4] |
| - 書いてて思ったけど、最後まで興味を持って読める人はまずいないだろうな・・・しくしく。まあCで使う分には気にしなくていい話だし・・・。 -- [[K]] &new{2008-12-23 (火) 23:01:36}; | | - 書いてて思ったけど、最後まで興味を持って読める人はまずいないだろうな・・・しくしく。まあCで使う分には気にしなくていい話だし・・・。 -- [[K]] &new{2008-12-23 (火) 23:01:36}; |
| + | - abcdw009のAPIパケットはこのページのabcdw007とは少し違います。いつかちゃんと書かないといけませんね。・・・とりあえず違いをメモしておくと、まず末尾の[3]はいらなくなりました。また32bitレジスタ指定方法が少し変わって、!6_0_?ではなく、!6_?になりました。8bitレジスタは、!6_!0x38がAL、!6_!0x39がCL・・・以下略になっています。あと、文字列表示APIの[5 0 ...]が[5 (0) ...]になりました。つまりAPI番号の5では、slot番号0は基本的には省略するということです。 -- ''K'' &new{2009-01-03 (土) 20:09:09}; |
| | | |
| #comment | | #comment |