因为在开发
CMinus的过程中为了异常处理(最终没有实现进CMinus),曾经学习了一下
怎么用汇编语言写try-catch,因此这个CPU相关的处理方法就被我偷了哈,实现在了
NativeX的虚拟机里。
在NativeX里面,try-catch和throw非常简单。throw你可以加一个值当异常数据,也可以不加(不会修改上次的异常数据,可以当rethrow用)。catch的话没办法跟C++一样根据类型来判断,因此我会给你一个异常数据的指针,你自己看着办哈,因为NativeX跟C一样没有RTTI。因此throw就很简单了,就是恢复栈顶和栈底指针之后跳转到最近的异常处理程序里面去。try和catch就是用来创建和销毁异常处理程序的。所有的异常处理程序构成了一个链表,这个链表被我记在了堆栈里面,而最近的异常处理节点的指针则被我放在了整个堆栈控件的最顶部,接在后面的是异常对象的数据。你每次throw的东西的尺寸可以不同,因此占用的“堆栈最顶部空间”也不同。当然如果你函数递归太深而导致栈顶覆盖了异常对象的数据区域时,就会触发“堆栈溢出”事件。在NativeX里面堆栈溢出代表你这程序已经废了,因此这个是不能catch的,虚拟机返回给宿主程序一个信号然后就停止执行了。
我们来看一个简单的例子,如何throw之后把异常对象的返回给函数,首先是代码:
1 /*NativeX Code*/
2 unit nativex_program_generated;
3 function int32 main()
4 {
5 (result = 10s32);
6 try
7 Throw();
8 catch
9 (result = ( * cast<int32*>(exception)));
10 }
11
12 function void Throw()
13 throw 20s32;
main函数首先将函数返回值设置成10,然后调用throw函数。throw函数会把20给throw出来,然后main函数catch了,把结果返回。NativeX使用了关键字exception来表达异常对象的地址。当然你如果要throw各种不同的东西的话,你得自己做标记(亲自实现RTTI)了。好了,我们看看产生的指令:
1 // unit nativex_program_generated;
2 0: stack_reserve 0
3 1: stack_reserve 0
4 2: ret 0
5 // function int32 main()
6 3: stack_reserve 0
7 // (result = 10s32);
8 4: push s32 10
9 5: resptr
10 6: write s32
11 // try
12 7: exception_handler_push 14
13 // Throw();
14 8: stack_reserve 1
15 9: stack_top 0
16 10: call 20 1
17 11: stack_reserve -1
18 // try
19 12: exception_handler_pop
20 13: jump 18 1
21 14: exception_handler_pop
22 // (result = ( * cast<int32*>(exception)));
23 15: exception_object_address
24 16: resptr
25 17: copymem 4
26 // function int32 main()
27 18: stack_reserve 0
28 19: ret 0
29 // function void Throw()
30 20: stack_reserve 0
31 // throw 20s32;
32 21: exception_object_reserve 4
33 22: push s32 20
34 23: exception_object_address
35 24: write s32
36 25: exception_raise
37 // function void Throw()
38 26: stack_reserve 0
39 27: ret 0
try首先会将catch之后的第一个指令给exception_handler_push了,在try的结尾当然要取消掉这个异常处理函数了,因此pop一下,然后jump到catch后面。当然catch的第一件事也是exception_handler_pop。exception_object_reserve在栈顶预留指定的空间来存放异常对象,exception_object_address则是获得异常对象的地址,exception_raise就是跳转到最近的异常处理函数了。raise不会把异常处理函数的记录给pop掉,所以要靠catch自己去pop。
NativeX已经完成了,接下来就可以开始打造周边工具了哇哈哈。将来的目标是将类似C#和Javascript的语言都编译到NativeX上,然后为这三类语言写很多语法分析器,然后他们就变成很多语言了。当然这些语言只是demo。
Vczh Library++的目的是提供实现编译器的中间每一层的类库,因此想干嘛就可以干嘛了哈。
posted on 2010-08-28 01:14
陈梓瀚(vczh) 阅读(3476)
评论(9) 编辑 收藏 引用 所属分类:
VL++3.0开发纪事