JIT脚本引擎:stdcall、cdecl和fastcall

JIT脚本引擎:stdcall、cdecl和fastcall
    stdcall、cdecl和fastcall的参数都是从右到左入栈,并且返回值遵循以下规律:
    小于等于4字节结构用EAX
    小于等于8字节结构用EDX:EAX
    浮点数用ST(0)
    其他则在EAX放置一个指针,供返回值使用

    stdcall被调用者清栈,cdecl调用者清栈,fastcall被调用者清栈并且前两个小于等于4字节的参数放入ECX和EDX。返回值和参数如果一方有构造函数或析构函数则不使用寄存器。

    于是今天用字符串形式的汇编写了三种调用方法的求和函数,类型如下:
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

    使用以下方法读取文件、编译并取出三个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 " 结果: " + 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 " 结果: " + 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 " 结果: " + 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  }

    得到结果:
JIT脚本引擎:stdcall、cdecl和fastcall_第1张图片

    接下来熟悉浮点数的操作,就可以开始中间指令集的构造了。

你可能感兴趣的:(JIT脚本引擎:stdcall、cdecl和fastcall)