はりぼて日記
2007 | 01 | 02 | 03 | 04 | 05 | 07 | 08 | 10
2006 | 11 | 12
10月 10 (水曜日) 2007
20:50
22日目2
 
------------約1時間後-----------------

・・・あーー! なるほどなるほど!
そういうことかぁ!

P439の_asm_hrb_api。ここを見てみてやっとわかった!

例えばだけど、現在のスタックの番地(ESPの値)が仮に0x1234だと過程する。この状態でPUSHADを二回行うと・・・


0x11F8 ediの値     ┬   ←現在のESPの値
0x11FB esiの値     │ (つまりスタックの番地)
0x1200 ebpの値     │
0x1204 espの値   2回目のPUSHAD
0x1208 ebxの値     │    
0x120B edxの値     │
0x1210 ecxの値     │
0x1214 eaxの値     ┴
0x1218 ediの値     ┬
0x121B esiの値     │
0x1220 ebpの値     │
0x1224 espの値   1回目のPUSHAD
0x1228 ebxの値     │    
0x122B edxの値     │
0x1230 ecxの値     │
0x1234 eaxの値     ┴


  • スタックはある番地を開始点として、PUSHされるごとに上の番地に進んでゆく(小さい番地へ向かう)
  • PUSHされるごとに番地は4づつ減ってゆく(4すなわち4バイト。4バイトとは32bit。32bitレジスタであるeaxなどの値がぴったり収まるようになっている)
  • P133、P134を参照のこと


こういう状態の後、C言語であるhrb_apiに渡される。
関数hrb_apiは各引数を、順にESP+4の倍数としてスタックから受け取る。つまり、0x11F8から int ediを、0x11FBから int esiを・・・・0x1214から int eaxを。こうして受け取っている。

・・・ここで、

int *reg = &eax+1;

という命令を行うと、ポインタである*regには引数である int eaxのお隣、すなわち0x1218が設定される。
(*regをint型で宣言しているため、4バイト刻みになる。なので、+1するということは4バイト先ということになる)

hrb_apiの後ろのほうで、

reg[7] = (int) sht;

という処理をしている。これは配列という意味ではなく、*regから7個お隣と言う意味として使われている。

すなわち、0x1234番地にshtの値が書き込まれたわけである。

この処理の後、hrb_apiはreturn命令で戻る。どこへ戻るのかといえば、自分を呼び出したasm_hrb_api(アセンブラプログラム)に戻ってゆく。

処理が戻ってきたasm_hrb_apiはアプリ終了かそうでないかを判断した後、

  ADD    ESP,32
POPAD

という処理をする。これはどういうことかというと、
本来ならPOPADを二回行うはずである。(だってPUSHADを二回やってるから。そうしないとつじつまが合わない)

しかし、当たり前だがPOPADはレジスタの値を書き換える。二回目にPUSHADした値はC言語実行の後だし意味がない。まるごと戻す必要がないのだ。

そこで、POPADはするがレジスタは書き換えない。そのため、ADD ESP,32を行う。これで、ESPの値すなわちスタックの番地が0x11F8から0x1228になる。

この状態でPOPAD!

レジスタには、0x1228〜0x1234の値が書き込まれ、元の状態に戻る。
(ただし、本当に元の状態ではない。0x1234の値は書き換えられている。)

これでIRETDを行い、処理を割り込み前のapi_openwinに戻す!

アセンブラプログラムであるapi_openwinは後処理をし、呼び出し元に戻る。

api_openwinを呼び出したのはC言語であるwinhelo.cである。
処理が終わると変数winに現在のEAXの値を代入して処理を終える。


・・・・ぷっはあぁぁぁぁ! やっとこさ整理できたーー!


・・・うーむ。ここいらへんはアセンブラやCを行ったり来たりなのでややこしいなぁ〜・・・
 
30日を過ぎたBlogにはコメントできません。

Referer  (11)
(1) 2 3 4 5 6 7 8 9 10 » 

PopnupBlog V3 Denali created by Bluemoon inc.