• <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
            這廝咋動作這么快呀!呵呵  回復  更多評論
              
            国产精品久久影院| 久久黄视频| 久久综合狠狠综合久久激情 | 欧美久久一区二区三区| 亚洲精品乱码久久久久久蜜桃| 午夜精品久久久内射近拍高清| 无码久久精品国产亚洲Av影片 | 久久婷婷五月综合色奶水99啪 | 欧美综合天天夜夜久久| 国产精品gz久久久| 中文字幕日本人妻久久久免费 | 久久只有这精品99| 91精品国产91久久久久福利| 久久久久亚洲av成人无码电影| 久久伊人五月丁香狠狠色| 高清免费久久午夜精品| 亚洲国产日韩欧美久久| 亚洲精品高清国产一久久| 久久99热这里只频精品6| 99久久国产综合精品成人影院 | 人妻久久久一区二区三区| 国产成人无码精品久久久免费| 国产aⅴ激情无码久久| 欧美一级久久久久久久大片| 国产V综合V亚洲欧美久久| 久久精品国产亚洲αv忘忧草 | 免费一级欧美大片久久网| 69久久夜色精品国产69| 精品熟女少妇AV免费久久| 久久精品国产一区二区三区不卡 | 精品国产乱码久久久久久浪潮| 精品久久亚洲中文无码| 久久婷婷色综合一区二区| 久久亚洲色一区二区三区| 日本精品久久久久中文字幕| 久久九九精品99国产精品| 97久久国产露脸精品国产| 欧美日韩久久中文字幕| 欧美久久综合九色综合| 亚洲欧美日韩精品久久亚洲区 | 亚洲精品乱码久久久久久久久久久久|