[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
#include <cstdio> using namespace std; class Formula { private: int a, b; public: Formula(int n, int d); ~Formula(); int res(); }; Formula::Formula(int n, int d) { a = n; b = d; } Formula::~Formula() {} int Formula::res() { return a + b; } int main() { Formula f1(1, 3); printf("%d\n", f1.res()); }ソース自体はなんの意味もないけど。
$ g++ test.cpp -g -o test $ objdump -d test > dump $ view dump逆アセンブルした結果がこちら(必要な部分だけの部分抜粋です)。
080484f4 <_ZN7FormulaC1Eii>: 80484f4: 55 push %ebp 80484f5: 89 e5 mov %esp,%ebp 80484f7: 8b 45 08 mov 0x8(%ebp),%eax 80484fa: 8b 55 0c mov 0xc(%ebp),%edx 80484fd: 89 10 mov %edx,(%eax) 80484ff: 8b 45 08 mov 0x8(%ebp),%eax 8048502: 8b 55 10 mov 0x10(%ebp),%edx 8048505: 89 50 04 mov %edx,0x4(%eax) 8048508: 5d pop %ebp 8048509: c3 ret 0804850a <_ZN7FormulaD1Ev>: 804850a: 55 push %ebp 804850b: 89 e5 mov %esp,%ebp 804850d: 5d pop %ebp 804850e: c3 ret 804850f: 90 nop 08048510 <_ZN7Formula3resEv>: 8048510: 55 push %ebp 8048511: 89 e5 mov %esp,%ebp 8048513: 8b 45 08 mov 0x8(%ebp),%eax 8048516: 8b 10 mov (%eax),%edx 8048518: 8b 45 08 mov 0x8(%ebp),%eax 804851b: 8b 40 04 mov 0x4(%eax),%eax 804851e: 01 d0 add %edx,%eax 8048520: 5d pop %ebp 8048521: c3 ret 08048522 <main>: 8048522: 55 push %ebp 8048523: 89 e5 mov %esp,%ebp 8048525: 53 push %ebx 8048526: 83 e4 f0 and $0xfffffff0,%esp 8048529: 83 ec 20 sub $0x20,%esp 804852c: c7 44 24 08 03 00 00 movl $0x3,0x8(%esp) 8048533: 00 8048534: c7 44 24 04 01 00 00 movl $0x1,0x4(%esp) 804853b: 00 804853c: 8d 44 24 18 lea 0x18(%esp),%eax 8048540: 89 04 24 mov %eax,(%esp) 8048543: e8 ac ff ff ff call 80484f4 <_ZN7FormulaC1Eii> 8048548: 8d 44 24 18 lea 0x18(%esp),%eax 804854c: 89 04 24 mov %eax,(%esp) 804854f: e8 bc ff ff ff call 8048510 <_ZN7Formula3resEv> 8048554: 89 44 24 04 mov %eax,0x4(%esp) 8048558: c7 04 24 70 86 04 08 movl $0x8048670,(%esp) 804855f: e8 ac fe ff ff call 8048410 <printf@plt> 8048564: 8d 44 24 18 lea 0x18(%esp),%eax 8048568: 89 04 24 mov %eax,(%esp) 804856b: e8 9a ff ff ff call 804850a <_ZN7FormulaD1Ev> 8048570: b8 00 00 00 00 mov $0x0,%eax 8048575: 8b 5d fc mov -0x4(%ebp),%ebx 8048578: c9 leave 8048579: c3 ret 804857a: 89 c3 mov %eax,%ebx 804857c: 8d 44 24 18 lea 0x18(%esp),%eax 8048580: 89 04 24 mov %eax,(%esp) 8048583: e8 82 ff ff ff call 804850a <_ZN7FormulaD1Ev> 8048588: 89 d8 mov %ebx,%eax 804858a: 89 04 24 mov %eax,(%esp) 804858d: e8 9e fe ff ff call 8048430 <_Unwind_Resume@plt> 8048592: 90 nop 8048593: 90 nop 8048594: 90 nop 8048595: 90 nop 8048596: 90 nop 8048597: 90 nop 8048598: 90 nop 8048599: 90 nop 804859a: 90 nop 804859b: 90 nop 804859c: 90 nop 804859d: 90 nop 804859e: 90 nop 804859f: 90 nopとりあえず、main関数のところをC言語風に逆コンパイルしてみると…
void main() { int d[2];// 0x18(%esp) ~ 0x1c(%esp)の部分 _ZN7FormulaC1Eii(d, 0x1, 0x3); int tmp = _ZN7Formula3resEv(d); printf((const char *)0x8048410, tmp); _ZN7FormulaD1Ev(d); return; }こんな感じになるのだろう。4行目でtmpを媒介にしたのは、あくまで読みやすさを追求しただけで、
void _ZN7FormulaC1Eii(int *d, int a, int b) { d[0] = a; d[1] = b; return; } void _ZN7FormulaD1Ev(int *d) { return; } int _ZN7Formula3resEv(int *d) { int tmp; tmp = d[0] + d[1]; return tmp; }これを元のメソッドと比較してみよう。
Formula::Formula(int n, int d) { a = n; b = d; } Formula::~Formula() {} int Formula::res() { return a + b; }何か決定的な違いがないだろうか?
COMMENT
804857a以降のコードとか
804857a以降のコードですが、例外周りで、デストラクタを呼び出すための物なのではないかと思います。(確証はありませんが)
以下のようにコードを修正し、アセンブリを吐かせると、何となく例外が絡んでそうなのが分かるのではないかと。
#include <cstdio>
using namespace std;
class Formula {
private:
int a, b;
public:
Formula(int n, int d);
~Formula();
int res();
};
Formula::Formula(int n, int d) {
a = n;
b = d;
}
Formula::~Formula() {
printf("class \"Formula\" deleted\n");
}
int Formula::res() {
return a + b;
}
int main() {
try {
Formula f1(1, 3);
throw(1);
printf("%d\n", f1.res());
} catch (int num) {
}
}
Re:804857a以降のコードとか
そうか…アセンブリを吐かせればよかったのか…。
と思ってやってみたんですが、throwがやはり__cxa_throwという
関数(に付随するもの?)で隠蔽されていて覗けず、
挫折してしまいました。
でも仰る通り、例外を入れる前後のバイナリを比較すると、
なんとなく例外をキャッチした部分でデストラクタを呼んでるんだな…という
感じはします。
とりあえず、PLT等勉強して行かないととてもアセンブリやバイナリを
読みこなすことはできなさそうなので、頑張って勉強を続けていきます。
(バイナリアンへの道は遠し!)