• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-341  評論-2670  文章-0  trackbacks-0
                Vczh Library++ 3.0終于實現(xiàn)跨Assembly調(diào)用函數(shù)了。其實在設(shè)計之初架構(gòu)就已經(jīng)允許了這個東西,只是一直都留著沒做。現(xiàn)在先看兩段代碼,然后逐一解釋指令的內(nèi)容。

                首先是第一個Assembly(可以認(rèn)為是dll,概念是一樣的),實現(xiàn)了一個全局變量,然后有一個單參數(shù)的函數(shù),返回參數(shù)跟全局變量的和(代碼是從語法樹生成出來的,主要是為了實現(xiàn)指令集里面的自動加注釋功能):
             1 /*NativeX Code*/
             2 unit nativex_program_generated;
             3 variable int32 leftOperand = 0;
             4 
             5 function int32 add(int32 rightOperand)
             6     (result=(leftOperand+rightOperand));
             7 
             8 
             9 /*Assembly*/
            10 .data
            11 0x0000000000 00 00 00 
            12 .label
            13      0: instruction 7
            14 .code
            15 // unit nativex_program_generated;
            16      0: stack_reserve 0
            17 // variable int32 leftOperand = 0;
            18      1: push s8 0
            19      2: convert s32 s8
            20      3: link_pushdata 0
            21      4: write s32
            22 // unit nativex_program_generated;
            23      5: stack_reserve 0
            24      6: ret 0
            25 // function int32 add(int32 rightOperand)
            26      7: stack_reserve 0
            27 // (result=(leftOperand+rightOperand));
            28      8: stack_offset 16
            29      9: read s32
            30     10: link_pushdata 0
            31     11: read s32
            32     12: add s32
            33     13: resptr
            34     14: write s32
            35 // function int32 add(int32 rightOperand)
            36     15: stack_reserve 0
            37     16: ret 4
            38 


                這段簡單的加法代碼沒什么好解釋的。窺孔優(yōu)化還沒做,因此會有一些垃圾在里面。在這里可以看到全局變量的訪問跟參數(shù)訪問的不同。全局變量使用link_pushdata,而參數(shù)使用stack_offset。link_開頭的都是鏈接時指令,鏈接器會把這些東西給轉(zhuǎn)換成真正的指令。因為在編譯的時候并不知道全局空間的實際指針,因此只好鏈接的時候再做,這個時候全局空間已經(jīng)生成出來了。最終link_pushdata會被轉(zhuǎn)換成一個push ptr x指令,x是一個常數(shù)。

                下面是調(diào)用這個Assembly里面的另一個Assembly的main函數(shù):

             1 /*NativeX Code*/
             2 unit nativex_program_generated;
             3 variable int32 adder alias programAdd.leftOperand;
             4 
             5 function int32 add(int32 offset) alias programAdd.add;
             6 
             7 function int32 main()
             8 {
             9     (adder=1);
            10     (result=add(2));
            11 }
            12 
            13 
            14 /*Assembly*/
            15 .data
            16 .label
            17      0: instruction 3
            18 .code
            19 // unit nativex_program_generated;
            20      0: stack_reserve 0
            21      1: stack_reserve 0
            22      2: ret 0
            23 // function int32 main()
            24      3: stack_reserve 0
            25 // (adder=1);
            26      4: push s8 1
            27      5: convert s32 s8
            28      6: link_pushforeigndata 0
            29      7: write s32
            30 // (result=add(2));
            31      8: push s8 2
            32      9: convert s32 s8
            33     10: resptr
            34     11: link_callforeignfunc 1
            35 // function int32 main()
            36     12: stack_reserve 0
            37     13: ret 0
            38 

                這里主要是看看一個Assembly里面的代碼是如何操作另外一個Assembly的東西的。首先定義鏈接符號,譬如說variable int32 adder alias programAdd.leftOperator。programAdd是第一個Assembly的名字(沒有反應(yīng)在代碼里),然后leftOperator明顯就是變量名了。因為Assembly的數(shù)據(jù)里面還保留了所有變量、函數(shù)、結(jié)構(gòu)類型的聲明的全部內(nèi)容,因此不會出現(xiàn)“Dll地獄”。鏈接的時候可以比較一下被鏈接的符號的聲明以及定義的連接符號的聲明是否吻合,不吻合則代表要么Assembly版本有問題,要么Assembly就是錯的,因此直接拋出異常不允許加載。

                在這個代碼里面我們有兩個符號:programAdd.leftOperator和programAdd.add。他們按照順序分別被套上ID:0和1。因此在對adder,也就是programAdd.leftOperator賦值的時候,這里使用了鏈接時指令link_pushforeigndata 0,用來讀入該變量的地址。調(diào)用add的時候,先push一個參數(shù)2,然后將存放結(jié)果的變量的指針也push進去,最后調(diào)用函數(shù)programAdd.add,也就是ID為1的符號了:link_callforeignfunc 1。

                鏈接器會把所有l(wèi)ink_開頭的指令全部通過已經(jīng)加載的信息重新替換成運行是指令。顯然link_pushforeigndata 0和link_callforeignfunc 1都是缺少加載時才有的信息才寫成這樣子的,最后會被翻譯成push ptr x和call assembly_id instruction_address。

                既然可以調(diào)用外部Assembly的函數(shù),那么把外部Assembly的函數(shù)的函數(shù)指針存放起來供以后調(diào)用也是完全可能的:
             1 /*NativeX Code*/
             2 unit nativex_program_generated;
             3 function int32 add(int32 a, int32 b)
             4     (result=(a+b));
             5 
             6 
             7 /*Assembly*/
             8 .data
             9 .label
            10      0: instruction 3
            11 .code
            12 // unit nativex_program_generated;
            13      0: stack_reserve 0
            14      1: stack_reserve 0
            15      2: ret 0
            16 // function int32 add(int32 a, int32 b)
            17      3: stack_reserve 0
            18 // (result=(a+b));
            19      4: stack_offset 20
            20      5: read s32
            21      6: stack_offset 16
            22      7: read s32
            23      8: add s32
            24      9: resptr
            25     10: write s32
            26 // function int32 add(int32 a, int32 b)
            27     11: stack_reserve 0
            28     12: ret 8
            29 

                這個我就不廢話了,更加簡單,連全局變量都沒有了,就一個加法函數(shù)。接下來的main函數(shù)會把這個加法函數(shù)和自己的加法函數(shù)的函數(shù)指針存下來,然后調(diào)用:
             1 /*NativeX Code*/
             2 unit nativex_program_generated;
             3 function int32 main()
             4 {
             5     variable function int32(int32, int32) padd1 = add1;
             6     variable function int32(int32, int32) padd2 = add2;
             7     variable int32 a = padd1(12);
             8     variable int32 b = padd2(34);
             9     (result=((a*10)+b));
            10 }
            11 
            12 function int32 add1(int32 a, int32 b) alias programAdd.add;
            13 
            14 function int32 add2(int32 a, int32 b)
            15     (result=(a+b));
            16 
            17 
            18 /*Assembly*/
            19 .data
            20 .label
            21      0: instruction 3
            22      1: instruction 40
            23 .code
            24 // unit nativex_program_generated;
            25      0: stack_reserve 0
            26      1: stack_reserve 0
            27      2: ret 0
            28 // function int32 main()
            29      3: stack_reserve 16
            30 // variable function int32(int32, int32) padd1 = add1;
            31      4: link_pushforeignfunc 0
            32      5: stack_offset -4
            33      6: write u32
            34 // variable function int32(int32, int32) padd2 = add2;
            35      7: link_pushfunc 1
            36      8: stack_offset -8
            37      9: write u32
            38 // variable int32 a = padd1(1, 2);
            39     10: push s8 2
            40     11: convert s32 s8
            41     12: push s8 1
            42     13: convert s32 s8
            43     14: stack_offset -12
            44     15: stack_offset -4
            45     16: read u32
            46     17: label
            47     18: call_indirect
            48 // variable int32 b = padd2(3, 4);
            49     19: push s8 4
            50     20: convert s32 s8
            51     21: push s8 3
            52     22: convert s32 s8
            53     23: stack_offset -16
            54     24: stack_offset -8
            55     25: read u32
            56     26: label
            57     27: call_indirect
            58 // (result=((a*10)+b));
            59     28: stack_offset -16
            60     29: read s32
            61     30: push s8 10
            62     31: convert s32 s8
            63     32: stack_offset -12
            64     33: read s32
            65     34: mul s32
            66     35: add s32
            67     36: resptr
            68     37: write s32
            69 // function int32 main()
            70     38: stack_reserve -16
            71     39: ret 0
            72 // function int32 add2(int32 a, int32 b)
            73     40: stack_reserve 0
            74 // (result=(a+b));
            75     41: stack_offset 20
            76     42: read s32
            77     43: stack_offset 16
            78     44: read s32
            79     45: add s32
            80     46: resptr
            81     47: write s32
            82 // function int32 add2(int32 a, int32 b)
            83     48: stack_reserve 0
            84     49: ret 8
            85 

                哇哈哈。

                最新代碼可以在這里獲得。
            posted on 2010-06-11 07:13 陳梓瀚(vczh) 閱讀(2540) 評論(3)  編輯 收藏 引用 所屬分類: VL++3.0開發(fā)紀(jì)事

            評論:
            # re: Vczh Library++ 3.0之實現(xiàn)跨Assembly調(diào)用函數(shù)內(nèi)幕 2010-06-11 23:58 | ccsdu2009
            內(nèi)幕?  回復(fù)  更多評論
              
            # re: Vczh Library++ 3.0之實現(xiàn)跨Assembly調(diào)用函數(shù)內(nèi)幕 2010-06-12 00:27 | 陳梓瀚(vczh)
            @ccsdu2009
            主要是在介紹鏈接器  回復(fù)  更多評論
              
            # re: Vczh Library++ 3.0之實現(xiàn)跨Assembly調(diào)用函數(shù)內(nèi)幕 2010-06-13 03:48 | radar
            (*@ο@*) 哇~  回復(fù)  更多評論
              
            精品久久一区二区| 亚洲国产精品久久久天堂| 无遮挡粉嫩小泬久久久久久久| 久久亚洲国产成人精品无码区| 一本大道久久a久久精品综合| 2020久久精品国产免费| 精品久久久久久| 久久亚洲精品中文字幕三区| 狠狠色噜噜狠狠狠狠狠色综合久久| 国产精品国色综合久久| 国产精品久久久久久久久| 国产精品久久久久久久| 狠狠色综合网站久久久久久久| 久久久久国色AV免费看图片| 久久精品国产一区二区三区不卡| 久久一本综合| 日产精品久久久久久久| 青青青国产精品国产精品久久久久| 日韩一区二区久久久久久| 久久精品免费大片国产大片| 久久九九兔免费精品6| 国产麻豆精品久久一二三| 97精品国产97久久久久久免费| 亚洲精品99久久久久中文字幕| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 久久人人爽人人爽人人片AV东京热| 亚洲精品高清国产一久久| 久久精品无码专区免费| 久久久久久久波多野结衣高潮| 国产精品久久毛片完整版| 久久最新免费视频| 91精品国产色综合久久| 色99久久久久高潮综合影院| AV色综合久久天堂AV色综合在| 久久亚洲2019中文字幕| 国产精品久久久久久福利69堂| 亚洲午夜福利精品久久| 66精品综合久久久久久久| 亚洲愉拍99热成人精品热久久| 久久黄色视频| 国内精品久久久久久麻豆 |