• <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
                光能編譯匯編還是不行的,因為很多東西在編譯的時候不知道,典型的比如放常量那部分的指針等等。主要原因還是因為x87(指FPU部分)沒有指令包含浮點立即數,所有裝載浮點常數的指令都要求提供指針。所以諸如double a=1.2;之類的代碼,需要將1.2預先放置在一個地方然后確定指針的位置。

                于是就遇到了一個問題,如何將編譯后才知道的指針地址寫進去呢?唯一的辦法就是在二進制代碼那里留空,然后使用一張新表記錄哪些地方是需要鏈接的時候填充的。于是可以使用如下結構來構造一張鏈接符號表:
            1 struct LinkingRef
            2 {
            3     VInt            ID;
            4     VInt            Offset;
            5     VSize            Position;
            6     VByte            Bits;//0->8, 1->16, 2->32
            7     VInt            Instruction;
            8 };
                其中ID代表鏈接的對象,譬如可以將0作為常數緩沖區的指針,其他數字作為外部函數的地址等等。Offset代表一個常量偏移,可以將ID所代表的地址加上一個數字之后存放在指令緩沖區的Position偏移處。至于地址的大小使用Bits來表達(因為整數也可以如此搞)。Instruction記錄的是使用這個鏈接單元的指令序號,用于生成錯誤信息。

                于是在編譯之后就可以填充鏈接信息,然后進行鏈接了。這個做完以后就只剩下一個問題了。我們不僅需要常量緩沖區、還需要變量緩沖區,那么如何在常量緩沖區填充之后鎖定呢(為了在試圖修改的時候拋出異常)?Windows API提供了VirtualAlloc、VirtualProtect和VirtualFree來幫我們完成這項工作。為了簡化操作,使用以下的類用于控制內存空間:
             1             struct VL_AsmExecutable
             2             {
             3             private:
             4                 VPointer                FConstantBuffer;
             5                 VPointer                FVariableBuffer;
             6                 VPointer                FInstructionBuffer;
             7                 VInt                    FConstantSize;
             8                 VInt                    FVariableSize;
             9                 VInt                    FInstructionSize;
            10                 VBool                    FAvailable;
            11 
            12             public:
            13                 VL_AsmExecutable();
            14                 ~VL_AsmExecutable();
            15 
            16                 void                    Allocate(VInt Constant , VInt Variable , VInt Instruction);
            17                 void                    Protect();
            18                 void                    Release();
            19                 VPointer                GetConstant();
            20                 VPointer                GetVariable();
            21                 VPointer                GetInstruction();
            22             };

                這里是實現部分:
             1             VL_AsmExecutable::VL_AsmExecutable()
             2             {
             3                 FConstantBuffer=0;
             4                 FVariableBuffer=0;
             5                 FInstructionBuffer=0;
             6                 FConstantSize=0;
             7                 FVariableSize=0;
             8                 FInstructionSize=0;
             9                 FAvailable=false;
            10             }
            11 
            12             VL_AsmExecutable::~VL_AsmExecutable()
            13             {
            14                 Release();
            15             }
            16 
            17             void VL_AsmExecutable::Allocate(VInt Constant , VInt Variable , VInt Instruction)
            18             {
            19                 Release();
            20                 FConstantSize=Constant?Constant:1;
            21                 FVariableSize=Variable?Variable:1;
            22                 FInstructionSize=Instruction?Instruction:1;
            23                 FConstantBuffer=VirtualAlloc(0,FConstantSize,MEM_COMMIT,PAGE_READWRITE);
            24                 FVariableBuffer=VirtualAlloc(0,FVariableSize,MEM_COMMIT,PAGE_READWRITE);
            25                 FInstructionBuffer=VirtualAlloc(0,FInstructionSize,MEM_COMMIT,PAGE_READWRITE);
            26                 FAvailable=true;
            27             }
            28 
            29             void VL_AsmExecutable::Protect()
            30             {
            31                 if(FAvailable)
            32                 {
            33                     DWORD OldProtect=0;
            34                     VirtualProtect(FConstantBuffer,FConstantSize,PAGE_READONLY,&OldProtect);
            35                     VirtualProtect(FInstructionBuffer,FInstructionSize,PAGE_EXECUTE_READ,&OldProtect);
            36                 }
            37             }
            38 
            39             void VL_AsmExecutable::Release()
            40             {
            41                 if(FAvailable)
            42                 {
            43                     VirtualFree(FConstantBuffer,FConstantSize,MEM_RELEASE);
            44                     VirtualFree(FVariableBuffer,FVariableSize,MEM_RELEASE);
            45                     VirtualFree(FInstructionBuffer,FInstructionSize,MEM_RELEASE);
            46                     
            47                     FConstantBuffer=0;
            48                     FVariableBuffer=0;
            49                     FInstructionBuffer=0;
            50                     FConstantSize=0;
            51                     FVariableSize=0;
            52                     FInstructionSize=0;
            53                     FAvailable=false;
            54                 }
            55             }
            56 
            57             VPointer VL_AsmExecutable::GetConstant()
            58             {
            59                 return FConstantBuffer;
            60             }
            61 
            62             VPointer VL_AsmExecutable::GetVariable()
            63             {
            64                 return FVariableBuffer;
            65             }
            66 
            67             VPointer VL_AsmExecutable::GetInstruction()
            68             {
            69                 return FInstructionBuffer;
            70             }

                到了這里就可以修改上一篇文章列出的匯編代碼了。我們將數組{10,1,2,3,4,5,6,7,8,9,10}存放進常量空間然后求和:
             1 VL_AsmCompiled* Compile()
             2 {
             3     VL_AsmProgram Program;
             4     {
             5         VInt Params[]={10,1,2,3,4,5,6,7,8,9,10};
             6         Program.ConstantBuffer.Write(&Params,sizeof(Params));
             7     }
             8     {
             9         // XOR EAX, EAX
            10         INSTRUCTION(XOR)
            11         PARAM_REG_32(EAX)
            12         PARAM_REG_32(EAX)
            13         // MOV EDI, #CONSTANT_BUFFER_POINTER
            14         INSTRUCTION(MOV)
            15         PARAM_REG_32(EDI)
            16         PARAM_IMM_32(0)
            17         LINK(VL_AsmProgram::CONSTANT_BUFFER_POINTER,0);
            18         // MOV ECX, [EDI]
            19         INSTRUCTION(MOV)
            20         PARAM_REG_32(ECX)
            21         PARAM_MI_32(NONE,1,EDI,0)
            22         // @BEGIN:
            23         LABEL(BEGIN)
            24             // CMP ECX, 0
            25             INSTRUCTION(CMP)
            26             PARAM_REG_32(ECX)
            27             PARAM_IMM_32(0)
            28             // JE @END
            29             INSTRUCTION(JE)
            30             PARAM_LABEL(END)
            31             // ADD EAX, [ECX * 4 + EDI]
            32             INSTRUCTION(ADD)
            33             PARAM_REG_32(EAX)
            34             PARAM_MI_32(ECX,4,EDI,0)
            35             // SUB ECX, 1
            36             INSTRUCTION(SUB)
            37             PARAM_REG_32(ECX)
            38             PARAM_IMM_32(1)
            39             // JMP @BEGIN
            40             INSTRUCTION(JMP)
            41             PARAM_LABEL(BEGIN)
            42         // @END:
            43         LABEL(END)
            44         // RET
            45         INSTRUCTION(RET)
            46     }
            47     VL_AsmCompiled* Compiled=Compile(&Program);
            48     if(Compiled->Errors.GetCount())
            49     {
            50         PrintErrors(Compiled);
            51         delete Compiled;
            52         return 0;
            53     }
            54     else
            55     {
            56         return Compiled;
            57     }
            58 }

                然后使用下面的代碼執行編譯后的機器碼:
             1 void RunExecutable(VL_AsmExecutable* Executable)
             2 {
             3     VPointer Buffer=Executable->GetInstruction();
             4     VInt Output=0;
             5     __asm
             6     {
             7         PUSHAD
             8         MOV EAX, dword ptr[Buffer]
             9         INT 3
            10         CALL EAX
            11         MOV dword ptr[Output], EAX
            12         POPAD
            13     }
            14     GetConsole()->Write(L"結果:EAX="+VUnicodeString(Output)+L"\r\n");
            15 }
            16 
            17 void vlmain()
            18 {
            19     GetConsole()->SetTitle(L"Vczh Library++ 2.0 Assembler");
            20     GetConsole()->SetTestMemoryLeaks(true);
            21     GetConsole()->SetPauseOnExit(true);
            22 
            23     VL_AsmCompiled* Compiled=Compile();
            24     if(Compiled)
            25     {
            26         VL_AsmExecutable* Executable=Link(Compiled);
            27         if(Compiled->Errors.GetCount())
            28         {
            29             PrintErrors(Compiled);
            30         }
            31         if(Executable)
            32         {
            33             RunExecutable(Executable);
            34             delete Executable;
            35         }
            36         delete Compiled;
            37     }
            38 }

                鏈接器就完成了。
            posted on 2009-02-22 22:41 陳梓瀚(vczh) 閱讀(1930) 評論(1)  編輯 收藏 引用 所屬分類: JIT

            評論:
            # re: JIT腳本引擎:完成鏈接器的核心功能 2009-02-23 05:21 | Corner Zhang
            這廝咋動作這么快呀!呵呵  回復  更多評論
              
            国产A级毛片久久久精品毛片| 国产亚洲精久久久久久无码AV| 久久久久久免费视频| 午夜天堂精品久久久久| 久久99热只有频精品8| 久久精品无码一区二区日韩AV| 久久婷婷是五月综合色狠狠| 久久亚洲私人国产精品vA| 青青国产成人久久91网| 中文字幕热久久久久久久| 色偷偷888欧美精品久久久| 日韩欧美亚洲综合久久| 久久精品一区二区国产| 久久亚洲中文字幕精品一区四| 亚洲女久久久噜噜噜熟女| 久久久受www免费人成| 久久久久亚洲Av无码专| 2021国产精品午夜久久| 久久AⅤ人妻少妇嫩草影院| 精品久久久久久中文字幕人妻最新| 久久九九免费高清视频| 国产成人精品久久一区二区三区 | 伊人久久大香线蕉综合Av| 亚洲成色999久久网站| 国产亚洲美女精品久久久2020| 久久精品国产福利国产琪琪| 东京热TOKYO综合久久精品| 亚洲AV无码久久精品色欲| 偷窥少妇久久久久久久久| 欧美日韩精品久久久免费观看| 国产精品激情综合久久| 精品精品国产自在久久高清 | 国产美女久久久| 蜜臀av性久久久久蜜臀aⅴ麻豆| 麻豆av久久av盛宴av| 天堂无码久久综合东京热| 久久久久亚洲AV成人网人人软件| 91精品久久久久久无码| 国产 亚洲 欧美 另类 久久| 日本道色综合久久影院| 99久久免费只有精品国产|