C++(アセンブリ)わけわからん…
#include<stdio.h> #include<iostream> #include<string.h> class Employee { public: int number; char name[128]; long pay; void ShowData(); void Test(); }; void Employee::ShowData() { printf("number: %d\n",number); printf("name: %s\n",name); printf("pay: %ld\n",pay); Test(); return; } void Employee::Test() { printf("Test function\n"); return; } int main(int argc, char * argv[]) { Employee yamato; printf("size: %lX\n",sizeof(Employee)); yamato.number = 0x1111; strcpy(yamato.name,"Ymamamoto"); yamato.pay = 0x100; yamato.ShowData(); return 0; }
g++ -m32 -g class.cpp
しました。
これをgdbでやると,
(gdb) disas main Dump of assembler code for function main(int, char**): 0x00001e40 <+0>: push ebp 0x00001e41 <+1>: mov ebp,esp 0x00001e43 <+3>: push edi 0x00001e44 <+4>: push esi 0x00001e45 <+5>: sub esp,0xb0 0x00001e4b <+11>: call 0x1e50 <main(int, char**)+16> 0x00001e50 <+16>: pop eax 0x00001e51 <+17>: mov ecx,DWORD PTR [ebp+0xc] 0x00001e54 <+20>: mov edx,DWORD PTR [ebp+0x8] 0x00001e57 <+23>: mov esi,DWORD PTR [eax+0x1b8] 0x00001e5d <+29>: mov esi,DWORD PTR [esi] 0x00001e5f <+31>: mov DWORD PTR [ebp-0xc],esi 0x00001e62 <+34>: lea esi,[eax+0x12d] 0x00001e68 <+40>: mov edi,0x88 0x00001e6d <+45>: mov DWORD PTR [ebp-0x10],0x0 0x00001e74 <+52>: mov DWORD PTR [ebp-0x14],edx 0x00001e77 <+55>: mov DWORD PTR [ebp-0x18],ecx 0x00001e7a <+58>: mov DWORD PTR [esp],esi 0x00001e7d <+61>: mov DWORD PTR [esp+0x4],0x88 0x00001e85 <+69>: mov DWORD PTR [ebp-0xa4],eax 0x00001e8b <+75>: mov DWORD PTR [ebp-0xa8],edi 0x00001e91 <+81>: call 0x1f18 0x00001e96 <+86>: mov ecx,DWORD PTR [ebp-0xa4] 0x00001e9c <+92>: lea edx,[ecx+0x138] 0x00001ea2 <+98>: lea esi,[ebp-0xa0] 0x00001ea8 <+104>: mov DWORD PTR [ebp-0xa0],0x1111 0x00001eb2 <+114>: add esi,0x4 0x00001eb8 <+120>: mov DWORD PTR [esp],esi 0x00001ebb <+123>: mov DWORD PTR [esp+0x4],edx 0x00001ebf <+127>: mov DWORD PTR [ebp-0xac],eax 0x00001ec5 <+133>: call 0x1f1e 0x00001eca <+138>: lea ecx,[ebp-0xa0] 0x00001ed0 <+144>: mov DWORD PTR [ebp-0x1c],0x100 0x00001ed7 <+151>: mov DWORD PTR [esp],ecx 0x00001eda <+154>: mov DWORD PTR [ebp-0xb0],eax 0x00001ee0 <+160>: call 0x1d80 <Employee::ShowData()> 0x00001ee5 <+165>: mov eax,DWORD PTR [ebp-0xa4] 0x00001eeb <+171>: mov ecx,DWORD PTR [eax+0x1b8] 0x00001ef1 <+177>: mov ecx,DWORD PTR [ecx] 0x00001ef3 <+179>: mov edx,DWORD PTR [ebp-0xc] 0x00001ef6 <+182>: cmp ecx,edx 0x00001ef8 <+184>: jne 0x1f0d <main(int, char**)+205> 0x00001efe <+190>: mov eax,0x0 0x00001f03 <+195>: add esp,0xb0 0x00001f09 <+201>: pop esi 0x00001f0a <+202>: pop edi 0x00001f0b <+203>: pop ebp 0x00001f0c <+204>: ret 0x00001f0d <+205>: call 0x1f12
わけわからん①
0x00001e40 <+0>: push ebp 0x00001e41 <+1>: mov ebp,esp 0x00001e43 <+3>: push edi 0x00001e44 <+4>: push esi 0x00001e45 <+5>: sub esp,0xb0
edi/esiをスタックにプッシュするの初めて見る。どの規約なんだろうか?
retnの後ろにスタックを調整するものもないし、__cdeclかな。多分.
わけわからん②
0x00001e4b <+11>: call 0x1e50 <main(int, char**)+16> 0x00001e50 <+16>: pop eax
なんか只々、次の行に進んでるだけにも見える。
その次、popしてる意味がわからん。
callしたら、自ずとretnの時点でeaxには関数の返り値は入ってるはず。
それをなぜあえて、スタックにpushされてた値をeaxに入れるのか。
それじゃあなんのためにcallしたのか。わからん。
わけわからん③
0x00001e51 <+17>: mov ecx,DWORD PTR [ebp+0xc] 0x00001e54 <+20>: mov edx,DWORD PTR [ebp+0x8]
(gdb) print 0xc
$1 = 12
多分、第2引数の値をecxに
第1引数の値をedxに代入…
ってmain関数に引数もなんもないやろ!
ってなってる。
わけわからん④
0x00001e57 <+23>: mov esi,DWORD PTR [eax+0x1b8] 0x00001e5d <+29>: mov esi,DWORD PTR [esi]
↑これ(eax)、なんのオフセットですか?
わけわからん⑤
>>> 0xb0
176
でしょ。
0x00001e6d <+45>: mov DWORD PTR [ebp-0x10],0x0 0x00001e74 <+52>: mov DWORD PTR [ebp-0x14],edx 0x00001e77 <+55>: mov DWORD PTR [ebp-0x18],ecx 0x00001e7a <+58>: mov DWORD PTR [esp],esi 0x00001e7d <+61>: mov DWORD PTR [esp+0x4],0x88 0x00001e85 <+69>: mov DWORD PTR [ebp-0xa4],eax 0x00001e8b <+75>: mov DWORD PTR [ebp-0xa8],edi
見る限り、ローカル変数の、第3、第2、第1順に考えて、
0x0,edx,ecxが代入されてる状態やね。
a = ecx;
b = edx;
c = 0x0;
ダメだ…途中で断念…
ここまで分かる人いますか?
【追記】
@ashigirl96 ①ただのレジスタをスタックに退避してるだけ。②mov eax,eipと等価。③int main(int argc, char**argv, char**env)
— 勇士Q (@ucq) 2014, 3月 7
↑のまんまですね。
なんでわかるのかがわからない。
③のint main(... ちょっとぐらい察してはいたけど
②とか理解できる意味がわからない…w
追々頑張っていきます…