因?yàn)樵陂_發(fā)
CMinus的過(guò)程中為了異常處理(最終沒(méi)有實(shí)現(xiàn)進(jìn)CMinus),曾經(jīng)學(xué)習(xí)了一下
怎么用匯編語(yǔ)言寫try-catch,因此這個(gè)CPU相關(guān)的處理方法就被我偷了哈,實(shí)現(xiàn)在了
NativeX的虛擬機(jī)里。
在NativeX里面,try-catch和throw非常簡(jiǎn)單。throw你可以加一個(gè)值當(dāng)異常數(shù)據(jù),也可以不加(不會(huì)修改上次的異常數(shù)據(jù),可以當(dāng)rethrow用)。catch的話沒(méi)辦法跟C++一樣根據(jù)類型來(lái)判斷,因此我會(huì)給你一個(gè)異常數(shù)據(jù)的指針,你自己看著辦哈,因?yàn)镹ativeX跟C一樣沒(méi)有RTTI。因此throw就很簡(jiǎn)單了,就是恢復(fù)棧頂和棧底指針之后跳轉(zhuǎn)到最近的異常處理程序里面去。try和catch就是用來(lái)創(chuàng)建和銷毀異常處理程序的。所有的異常處理程序構(gòu)成了一個(gè)鏈表,這個(gè)鏈表被我記在了堆棧里面,而最近的異常處理節(jié)點(diǎn)的指針則被我放在了整個(gè)堆棧控件的最頂部,接在后面的是異常對(duì)象的數(shù)據(jù)。你每次throw的東西的尺寸可以不同,因此占用的“堆棧最頂部空間”也不同。當(dāng)然如果你函數(shù)遞歸太深而導(dǎo)致棧頂覆蓋了異常對(duì)象的數(shù)據(jù)區(qū)域時(shí),就會(huì)觸發(fā)“堆棧溢出”事件。在NativeX里面堆棧溢出代表你這程序已經(jīng)廢了,因此這個(gè)是不能catch的,虛擬機(jī)返回給宿主程序一個(gè)信號(hào)然后就停止執(zhí)行了。
我們來(lái)看一個(gè)簡(jiǎn)單的例子,如何throw之后把異常對(duì)象的返回給函數(shù),首先是代碼:
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函數(shù)首先將函數(shù)返回值設(shè)置成10,然后調(diào)用throw函數(shù)。throw函數(shù)會(huì)把20給throw出來(lái),然后main函數(shù)catch了,把結(jié)果返回。NativeX使用了關(guān)鍵字exception來(lái)表達(dá)異常對(duì)象的地址。當(dāng)然你如果要throw各種不同的東西的話,你得自己做標(biāo)記(親自實(shí)現(xiàn)RTTI)了。好了,我們看看產(chǎn)生的指令:
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首先會(huì)將catch之后的第一個(gè)指令給exception_handler_push了,在try的結(jié)尾當(dāng)然要取消掉這個(gè)異常處理函數(shù)了,因此pop一下,然后jump到catch后面。當(dāng)然catch的第一件事也是exception_handler_pop。exception_object_reserve在棧頂預(yù)留指定的空間來(lái)存放異常對(duì)象,exception_object_address則是獲得異常對(duì)象的地址,exception_raise就是跳轉(zhuǎn)到最近的異常處理函數(shù)了。raise不會(huì)把異常處理函數(shù)的記錄給pop掉,所以要靠catch自己去pop。
NativeX已經(jīng)完成了,接下來(lái)就可以開始打造周邊工具了哇哈哈。將來(lái)的目標(biāo)是將類似C#和Javascript的語(yǔ)言都編譯到NativeX上,然后為這三類語(yǔ)言寫很多語(yǔ)法分析器,然后他們就變成很多語(yǔ)言了。當(dāng)然這些語(yǔ)言只是demo。
Vczh Library++的目的是提供實(shí)現(xiàn)編譯器的中間每一層的類庫(kù),因此想干嘛就可以干嘛了哈。
posted on 2010-08-28 01:14
陳梓瀚(vczh) 閱讀(3502)
評(píng)論(9) 編輯 收藏 引用 所屬分類:
VL++3.0開發(fā)紀(jì)事