• <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  評(píng)論-2670  文章-0  trackbacks-0
                stdcall、cdecl和fastcall的參數(shù)都是從右到左入棧,并且返回值遵循以下規(guī)律:
                小于等于4字節(jié)結(jié)構(gòu)用EAX
                小于等于8字節(jié)結(jié)構(gòu)用EDX:EAX
                浮點(diǎn)數(shù)用ST(0)
                其他則在EAX放置一個(gè)指針,供返回值使用

                stdcall被調(diào)用者清棧,cdecl調(diào)用者清棧,fastcall被調(diào)用者清棧并且前兩個(gè)小于等于4字節(jié)的參數(shù)放入ECX和EDX。返回值和參數(shù)如果一方有構(gòu)造函數(shù)或析構(gòu)函數(shù)則不使用寄存器。

                于是今天用字符串形式的匯編寫(xiě)了三種調(diào)用方法的求和函數(shù),類(lèi)型如下:
            1 typedef VInt (__stdcall * Summer_Stdcall)(VInt* Numbers , VInt Count);
            2 typedef VInt (__cdecl * Summer_Cdecl)(VInt* Numbers , VInt Count);
            3 typedef VInt (__fastcall * Summer_Fastcall)(VInt* Numbers , VInt Count);

                匯編代碼如下:
             1 CONSTANT
             2 VARIABLE
             3 CODE
             4 
             5 @SUM_STDCALL:
             6   PUSH EBP
             7   MOV EBP, ESP
             8   PUSH ECX
             9   PUSH EDI
            10   XOR EAX, EAX
            11   MOV ECX, int32 [EBP+12]
            12   MOV EDI, int32 [EBP+8]
            13 @SUM_STDCALL_BEGIN:
            14   CMP ECX, int32 0
            15   JE @SUM_STDCALL_FINISHED
            16   ADD EAX, int32 [EDI]
            17   ADD EDI, int32 4
            18   DEC ECX
            19   JMP @SUM_STDCALL_BEGIN
            20 @SUM_STDCALL_FINISHED:
            21   POP EDI
            22   POP ECX
            23   MOV ESP, EBP
            24   POP EBP
            25   RET int16 8
            26 
            27 @SUM_CDECL:
            28   PUSH EBP
            29   MOV EBP, ESP
            30   PUSH ECX
            31   PUSH EDI
            32   XOR EAX, EAX
            33   MOV ECX, int32 [EBP+12]
            34   MOV EDI, int32 [EBP+8]
            35 @SUM_CDECL_BEGIN:
            36   CMP ECX, int32 0
            37   JE @SUM_CDECL_FINISHED
            38   ADD EAX, int32 [EDI]
            39   ADD EDI, int32 4
            40   DEC ECX
            41   JMP @SUM_CDECL_BEGIN
            42 @SUM_CDECL_FINISHED:
            43   POP EDI
            44   POP ECX
            45   MOV ESP, EBP
            46   POP EBP
            47   RET
            48 
            49 @SUM_FASTCALL:
            50   PUSH EBP
            51   MOV EBP, ESP
            52   XOR EAX, EAX
            53 @SUM_FASTCALL_BEGIN:
            54   CMP EDX, int32 0
            55   JE @SUM_FASTCALL_FINISHED
            56   ADD EAX, int32 [ECX]
            57   ADD ECX, int32 4
            58   DEC EDX
            59   JMP @SUM_FASTCALL_BEGIN
            60 @SUM_FASTCALL_FINISHED:
            61   MOV ESP, EBP
            62   POP EBP
            63   RET

                使用以下方法讀取文件、編譯并取出三個(gè)label的指針:
             1 void RunExecutable(VL_AsmProgram* Program , VL_AsmCompiled* Compiled , VL_AsmExecutable* Executable)
             2 {
             3     VInt Numbers[]={11,12,13,14,15,16,17,18,19,20};
             4     VInt Count=sizeof(Numbers)/sizeof(*Numbers);
             5     {
             6         VInt Offset=(VInt)Compiled->LabelOffsets[Program->LabelNames.IndexOf(L"@SUM_STDCALL")];
             7         Summer_Stdcall Summer=(Summer_Stdcall)((VInt)Executable->GetInstruction()+Offset);
             8         VInt Result=Summer(Numbers,Count);
             9         GetConsole()->Write(L"結(jié)果:"+VUnicodeString(Result)+L"\r\n");
            10     }
            11     {
            12         VInt Offset=(VInt)Compiled->LabelOffsets[Program->LabelNames.IndexOf(L"@SUM_CDECL")];
            13         Summer_Cdecl Summer=(Summer_Cdecl)((VInt)Executable->GetInstruction()+Offset);
            14         VInt Result=Summer(Numbers,Count);
            15         GetConsole()->Write(L"結(jié)果:"+VUnicodeString(Result)+L"\r\n");
            16     }
            17     {
            18         VInt Offset=(VInt)Compiled->LabelOffsets[Program->LabelNames.IndexOf(L"@SUM_FASTCALL")];
            19         Summer_Fastcall Summer=(Summer_Fastcall)((VInt)Executable->GetInstruction()+Offset);
            20         VInt Result=Summer(Numbers,Count);
            21         GetConsole()->Write(L"結(jié)果:"+VUnicodeString(Result)+L"\r\n");
            22     }
            23 }
            24 
            25 void Main_Assembler()
            26 {
            27     VUnicodeString Code;
            28     VInt Line=0;
            29     VUnicodeString Message;
            30     {
            31         VUnicodeString WorkData=VFileName(GetConsole()->GetAppPath()).MakeAbsolute(L"..\\..\\TestData\\").GetStrW();
            32         VL_FileStream CodeStream(WorkData+L"Assembly.txt",VL_FileStream::vomRead);
            33         Code=ReadText(&CodeStream);
            34     }
            35 
            36     VL_AsmProgram* Program=CompileToAssembly(Code,Line,Message);
            37     if(!Program)
            38     {
            39         GetConsole()->Write(Message);
            40         return;
            41     }
            42 
            43     VL_AsmCompiled* Compiled=CompileToX86(Program);
            44     if(Compiled->Errors.GetCount())
            45     {
            46         PrintErrors(Program,Compiled);
            47         delete Program;
            48         delete Compiled;
            49         return;
            50     }
            51 
            52     VL_AsmExecutable* Executable=LinkX86(Compiled);
            53     if(Compiled->Errors.GetCount())
            54     {
            55         PrintErrors(Program,Compiled);
            56     }
            57     if(Executable)
            58     {
            59         RunExecutable(Program,Compiled,Executable);
            60         delete Executable;
            61     }
            62     delete Program;
            63     delete Compiled;
            64 }

                得到結(jié)果:

                接下來(lái)熟悉浮點(diǎn)數(shù)的操作,就可以開(kāi)始中間指令集的構(gòu)造了。
            posted on 2009-03-01 05:27 陳梓瀚(vczh) 閱讀(1801) 評(píng)論(9)  編輯 收藏 引用 所屬分類(lèi): JIT

            評(píng)論:
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-03 05:39 | lnn
            To day is my birthday!  回復(fù)  更多評(píng)論
              
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-03 21:20 | OwnWaterloo
            --------------------------------------------------------------------------------------------
            stdcall、cdecl和fastcall的參數(shù)都是從右到左入棧,并且返回值遵循以下規(guī)律:
                小于等于4字節(jié)結(jié)構(gòu)用EAX
                小于等于8字節(jié)結(jié)構(gòu)用EDX:EAX
                浮點(diǎn)數(shù)用ST(0)
                其他則在EAX放置一個(gè)指針,供返回值使用
            --------------------------------------------------------------------------------------------
             
            請(qǐng)問(wèn)一下,關(guān)于這個(gè)規(guī)律,是有標(biāo)準(zhǔn)規(guī)定的嗎?
            C/C++的書(shū)籍或者標(biāo)準(zhǔn)中,都沒(méi)有規(guī)定調(diào)用約定。
            還是說(shuō),這些只是事實(shí)上的標(biāo)準(zhǔn)?
             
            如果只是事實(shí)上的標(biāo)準(zhǔn),這些規(guī)律的應(yīng)用范圍只限于x86以及其兼容機(jī)?
              回復(fù)  更多評(píng)論
              
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-04 09:27 | 路人戊
            @OwnWaterloo
            參數(shù)入棧方向沒(méi)有標(biāo)準(zhǔn),甚至沒(méi)有事實(shí)上的標(biāo)準(zhǔn),IA86上GCC和VC編譯器方向就不同。
            其他寄存器多的CPU編譯器傾向盡可能地利用寄存器來(lái)傳遞參數(shù),會(huì)出現(xiàn)調(diào)用函數(shù)壓棧就只是壓進(jìn)一個(gè)返回地址的情形

            一擊脫離……  回復(fù)  更多評(píng)論
              
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-04 19:20 | 陳梓瀚(vczh)
            @路人戊
            這是windows下編譯器的約定,windows下的vc++、gcc和c++builder都遵守這個(gè)約定。至于其他的怎么辦其實(shí)都無(wú)所謂了,因?yàn)閣indows的程序只能直接調(diào)用windows的程序。  回復(fù)  更多評(píng)論
              
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-04 19:21 | 陳梓瀚(vczh)
            @OwnWaterloo
            這在msdn里有詳細(xì)描述。  回復(fù)  更多評(píng)論
              
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-04 23:44 | OwnWaterloo
            @陳梓瀚(vczh)
            MSDN就是微軟的編譯器了。

            其他的編譯器是否也是這樣?

            雖然我也覺(jué)得其他編譯器也應(yīng)該是這樣。
            沒(méi)有理由無(wú)故的與樓主描述的__cdecl,__stdcall實(shí)現(xiàn)不兼容。

            但是心里沒(méi)譜啊 ……
            樓主作過(guò)其他編譯器的調(diào)查么?
            有前人作過(guò)類(lèi)似的調(diào)查么?
              回復(fù)  更多評(píng)論
              
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-05 00:07 | 陳梓瀚(vczh)
            @OwnWaterloo
            我以前用的是C++Builder,根據(jù)觀察一致。而且這里有一個(gè)很強(qiáng)大的理由,如果不兼容的話,怎么調(diào)API?所以必須兼容。  回復(fù)  更多評(píng)論
              
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-05 03:03 | OwnWaterloo
            @陳梓瀚(vczh)
            ---------------------------------------------
            如果不兼容的話,怎么調(diào)API?所以必須兼容。
            ---------------------------------------------
            ---------------------------------------------
            雖然我也覺(jué)得其他編譯器也應(yīng)該是這樣。
            沒(méi)有理由無(wú)故的與樓主描述的__cdecl,__stdcall實(shí)現(xiàn)不兼容。
            ---------------------------------------------
            我想說(shuō)的就是這個(gè)意思,應(yīng)該不會(huì)有編譯器放棄大多數(shù)舊有的C目標(biāo)文件遵守的約定,另尋它法。


            但是呢。。。 還是不像有個(gè)ISO那么有把握。


            http://www.unixwiz.net/techtips/win32-callconv.html
            這篇文章里說(shuō)了一個(gè)入棧順序,和平時(shí)所說(shuō)的右到左不同。
            但在win32上結(jié)論是一樣的。

              回復(fù)  更多評(píng)論
              
            # re: JIT腳本引擎:stdcall、cdecl和fastcall 2009-03-05 04:45 | 陳梓瀚(vczh)
            @OwnWaterloo
            有了ISO也不見(jiàn)得就怎么樣  回復(fù)  更多評(píng)論
              
            久久精品二区| 久久精品桃花综合| 少妇熟女久久综合网色欲| 久久精品无码专区免费东京热 | 久久久久人妻一区二区三区vr| 国产精品激情综合久久| 久久久老熟女一区二区三区| 久久无码一区二区三区少妇| 亚洲国产精品婷婷久久| 久久久久免费看成人影片| 2021国内久久精品| 精品无码久久久久久久久久| 国产高潮国产高潮久久久| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 一本一本久久A久久综合精品| 很黄很污的网站久久mimi色 | 久久久久久青草大香综合精品| 久久最新精品国产| 69SEX久久精品国产麻豆| 久久香综合精品久久伊人| 久久久久国产精品嫩草影院| 尹人香蕉久久99天天拍| 亚洲精品无码久久久久AV麻豆| 久久久青草青青国产亚洲免观| 国产精品内射久久久久欢欢 | 久久精品aⅴ无码中文字字幕不卡| 久久久久亚洲AV无码专区桃色 | 国产巨作麻豆欧美亚洲综合久久| 久久久91精品国产一区二区三区| 69SEX久久精品国产麻豆| 国产精品久久久久aaaa| 996久久国产精品线观看| 99久久超碰中文字幕伊人| 99久久这里只有精品| 精品久久香蕉国产线看观看亚洲| MM131亚洲国产美女久久| 久久久91精品国产一区二区三区| 99久久www免费人成精品| 久久97久久97精品免视看| 日本久久中文字幕| 久久中文字幕人妻熟av女|