demonstrate 的 blog » 日志 » 编译器是如何实现 try ... catch 的?
编译器是如何实现 try ... catch 的?
demonstrate 发表于 2006-10-27 14:30:44
下面有这么一段 C++ 代码:
call 的函数式编译器产生的,其中 ms 传入了一个参数,也就是 4013e5 那句 movl 传的 1 。
之后 4013f6 处 call 的是 A 的构造函数,传入的参数来自于 EAX,但是实际上我们的构造函数
并没有参数。最后 40140e 处 call 的也是编译器自己产生的函数,带有三个参数,4013fb 处的
0x0 和 401403 处的 0x43eeec,还有寄存器 EBX 的内容,这使得我们必须看看 ___cxa_allocate_exception
产生了什么放在 EAX 中传回...
注意,因为 exception 是编译器实现不同的,因此这部分不能推广到其他的编译器上。
#include <iostream>这是汇编的结果,我们仔细研究一下 GCC 怎么完成的 try catch 功能。
using namespace std ;
class A {
public:
A() {
}
} ;
void
f( void )
{
throw A( ) ;
}
int
main( int argc, char *argv[] )
{
try {
f( ) ;
}
catch( A &e ) {
cout << "Exception occured!" << endl ;
}
return 0 ;
}
00401414 <_main>:现在看不懂啊... 下面是 f 的汇编代码
401414: 55 push %ebp
401415: 89 e5 mov %esp,%ebp
401417: 57 push %edi
401418: 56 push %esi
401419: 53 push %ebx
40141a: 83 ec 5c sub 0x5c,%esp
40141d: 83 e4 f0 and 0xfffffff0,%esp
401420: b8 00 00 00 00 mov 0x0,%eax
401425: 83 c0 0f add 0xf,%eax
401428: 83 c0 0f add 0xf,%eax
40142b: c1 e8 04 shr 0x4,%eax
40142e: c1 e0 04 shl 0x4,%eax
401431: 89 45 a8 mov %eax,0xffffffa8(%ebp)
401434: 8b 45 a8 mov 0xffffffa8(%ebp),%eax
401437: e8 84 c8 00 00 call 40dcc0 <___chkstk>
40143c: c7 45 d4 e0 19 40 00 movl 0x4019e0,0xffffffd4(%ebp)
401443: c7 45 d8 6c b8 43 00 movl 0x43b86c,0xffffffd8(%ebp)
40144a: 8d 45 dc lea 0xffffffdc(%ebp),%eax
40144d: 8d 55 f4 lea 0xfffffff4(%ebp),%edx
401450: 89 10 mov %edx,(%eax)
401452: ba d1 14 40 00 mov 0x4014d1,%edx
401457: 89 50 04 mov %edx,0x4(%eax)
40145a: 89 60 08 mov %esp,0x8(%eax)
40145d: 8d 45 bc lea 0xffffffbc(%ebp),%eax
401460: 89 04 24 mov %eax,(%esp)
401463: e8 08 be 00 00 call 40d270 <__Unwind_SjLj_Register>
401468: e8 63 b9 00 00 call 40cdd0 <___main>
40146d: c7 45 c0 02 00 00 00 movl 0x2,0xffffffc0(%ebp)
401474: e8 65 ff ff ff call 4013de <__Z1fv>
401479: e9 92 00 00 00 jmp 401510 <_main+0xfc>
40147e: 83 7d ac 01 cmpl 0x1,0xffffffac(%ebp)
401482: 74 12 je 401496 <_main+0x82>
401484: 8b 45 b4 mov 0xffffffb4(%ebp),%eax
401487: 89 04 24 mov %eax,(%esp)
40148a: c7 45 c0 ff ff ff ff movl 0xffffffff,0xffffffc0(%ebp)
401491: e8 9a c4 00 00 call 40d930 <__Unwind_SjLj_Resume>
401496: 8b 55 b4 mov 0xffffffb4(%ebp),%edx
401499: 89 14 24 mov %edx,(%esp)
40149c: e8 0f 2d 00 00 call 4041b0 <___cxa_begin_catch>
4014a1: 89 45 f0 mov %eax,0xfffffff0(%ebp)
4014a4: c7 44 24 04 00 e0 43 movl 0x43e000,0x4(%esp)
4014ab: 00
4014ab: 00
4014ac: c7 04 24 c0 13 44 00 movl 0x4413c0,(%esp)
4014b3: c7 45 c0 01 00 00 00 movl 0x1,0xffffffc0(%ebp) EERSt13basic_ostreamIcT_ES5_PKc>
4014bf: c7 44 24 04 70 8c 43 movl 0x438c70,0x4(%esp)
4014c6: 00
4014c7: 89 04 24 mov %eax,(%esp)
4014ca: e8 49 74 02 00 call 428918 <__ZNSolsEPFRSoS_E>
4014cf: eb 3a jmp 40150b <_main+0xf7>
4014d1: 8d 6d 0c lea 0xc(%ebp),%ebp
4014d4: 8b 45 c0 mov 0xffffffc0(%ebp),%eax
4014d7: 8b 55 c4 mov 0xffffffc4(%ebp),%edx
4014da: 89 55 b4 mov %edx,0xffffffb4(%ebp)
4014dd: 8b 55 c8 mov 0xffffffc8(%ebp),%edx
4014e0: 89 55 ac mov %edx,0xffffffac(%ebp)
4014e3: 83 f8 01 cmp 0x1,%eax
4014e6: 74 96 je 40147e <_main+0x6a>
4014e8: 8b 45 b4 mov 0xffffffb4(%ebp),%eax
4014eb: 89 45 b0 mov %eax,0xffffffb0(%ebp)
4014ee: e8 cd 2d 00 00 call 4042c0 <___cxa_end_catch>
4014f3: 8b 55 b0 mov 0xffffffb0(%ebp),%edx
4014f6: 89 55 b4 mov %edx,0xffffffb4(%ebp)
4014f9: 8b 45 b4 mov 0xffffffb4(%ebp),%eax
4014fc: 89 04 24 mov %eax,(%esp)
4014ff: c7 45 c0 ff ff ff ff movl 0xffffffff,0xffffffc0(%ebp)
401506: e8 25 c4 00 00 call 40d930 <__Unwind_SjLj_Resume>
40150b: e8 b0 2d 00 00 call 4042c0 <___cxa_end_catch>
401510: c7 45 b8 00 00 00 00 movl 0x0,0xffffffb8(%ebp)
401517: 8d 45 bc lea 0xffffffbc(%ebp),%eax
40151a: 89 04 24 mov %eax,(%esp)
401522: 8b 45 b8 mov 0xffffffb8(%ebp),%eax
401525: 8d 65 f4 lea 0xfffffff4(%ebp),%esp
401528: 5b pop %ebx
401529: 5e pop %esi
40152a: 5f pop %edi
40152b: 5d pop %ebp
40152c: c3 ret
40152d: 90 nop
004013de <__Z1fv>:注意到 f 简单到一句话,可见 throw 本身实现起来是需要一定的技巧的。首先在 4013ec 部分
4013de: 55 push %ebp
4013df: 89 e5 mov %esp,%ebp
4013e1: 53 push %ebx
4013e2: 83 ec 14 sub #CONTENT#x14,%esp
4013e5: c7 04 24 01 00 00 00 movl #CONTENT#x1,(%esp)
4013ec: e8 2f 2b 00 00 call 403f20 <___cxa_allocate_exception>
4013f1: 89 c3 mov %eax,%ebx
4013f3: 89 1c 24 mov %ebx,(%esp)
4013f6: e8 65 f7 00 00 call 410b60 <__ZN1AC1Ev>
4013fb: c7 44 24 08 00 00 00 movl #CONTENT#x0,0x8(%esp)
401402: 00
401403: c7 44 24 04 ec ee 43 movl #CONTENT#x43eeec,0x4(%esp)
40140a: 00
40140b: 89 1c 24 mov %ebx,(%esp)
40140e: e8 1d 2a 00 00 call 403e30 <___cxa_throw>
401413: 90 nop
call 的函数式编译器产生的,其中 ms 传入了一个参数,也就是 4013e5 那句 movl 传的 1 。
之后 4013f6 处 call 的是 A 的构造函数,传入的参数来自于 EAX,但是实际上我们的构造函数
并没有参数。最后 40140e 处 call 的也是编译器自己产生的函数,带有三个参数,4013fb 处的
0x0 和 401403 处的 0x43eeec,还有寄存器 EBX 的内容,这使得我们必须看看 ___cxa_allocate_exception
产生了什么放在 EAX 中传回...
注意,因为 exception 是编译器实现不同的,因此这部分不能推广到其他的编译器上。
曾经的这一天...
- » 2005年: algorithm 今天的任务还有三章...
- » 2005年: 头痛...
- » 2005年: 继续傻 b
- » 2005年: 傻 b 的问题...
- » 2005年: 忏悔中...
- » 2005年: algorithm 复习计划
- » 2005年: 不能死耗着了!!!!
相关日志:
收藏:
QQ书签
del.icio.us
订阅:
Google
抓虾
