JIT脚本引擎:浮点运算

JIT脚本引擎:浮点运算
    x87的FPU支持很多种浮点运算,其中浮点运算的比较结果不放在EFLAGS里,我们需要人手取出。在比较a和b的时候,C2=0,C3=(a==b),C0=(a<b)。我们可以将FNSTSW AX指令将浮点标志位复制到AX,然后通过读取C3、C2和C0(分别位于第14、10、8位)来判断结果。下面是一个求浮点数组最大值的汇编函数:

 1  CONSTANT
 2  VARIABLE
 3  CODE
 4 
 5  // double __stdcall double_max(double* numbers , int count)
 6  @DOUBLE_MAX:
 7     // 新建堆栈帧
 8    PUSH EBP
 9    MOV EBP, ESP
10    PUSH EAX  // floating status word
11    PUSH EBX  // numbers
12    PUSH ECX  // looping variable
13    PUSH EDX  // count
14     // temp=numbers[0]
15    SUB ESP, int32  8
16    MOV EBX, int32 [EBP + 8 ]
17    FLD fp64 [EBX]
18    FSTP fp64 [ESP]
19     // for(ECX=1;ECX<count;ECX++)
20    MOV ECX, int32  1
21    MOV EDX, int32 [EBP + 12 ]
22  @DOUBLE_MAX_LOOP_BEGIN:
23    CMP ECX, EDX
24    JZ @DOUBLE_MAX_LOOP_END
25     // temp=MAX(temp,numbers[ECX])
26    FLD fp64 [ESP]
27    FCOMP fp64 [ECX * 8 + EBX]
28    FNSTSW AX
29    TEST AH, int8  1
30    JZ @DOUBLE_MAX_LOOP_SIDEEFFECT
31    FLD fp64 [ECX * 8 + EBX]
32    FSTP fp64[ESP]
33  @DOUBLE_MAX_LOOP_SIDEEFFECT:
34    INC ECX
35    JMP @DOUBLE_MAX_LOOP_BEGIN
36  @DOUBLE_MAX_LOOP_END:
37     // return temp
38    FLD fp64 [ESP]
39     // 销毁堆栈帧
40    ADD ESP, int32  8
41    POP EDX
42    POP ECX
43    POP EBX
44    POP EAX
45    MOV ESP, EBP
46    POP EBP
47    RET int16  8

    我们可以通过一下代码调用此函数:
 1  typedef  double (__stdcall * ASM_MAX)( double *  Numbers ,  int  Count);
 2 
 3  void  RunExecutable(VL_AsmProgram *  Program , VL_AsmCompiled *  Compiled , VL_AsmExecutable *  Executable)
 4  {
 5      VInt Offset = (VInt)Compiled -> LabelOffsets[Program -> LabelNames.IndexOf(L " @DOUBLE_MAX " )];
 6      ASM_MAX Function = (ASM_MAX)((VInt)Executable -> GetInstruction() + Offset);
 7       double  Numbers[] = { 7 , 1 , 12 , 2 , 8 , 3 , 11 , 4 , 9 , 5 , 13 , 6 , 10 };
 8       double  Max = Function(Numbers, sizeof (Numbers) / sizeof ( * Numbers));
 9      GetConsole() -> Write(L " 结果: " + VUnicodeString(Max) + L " \r\n " );
10  }

    得到如下结果:
JIT脚本引擎:浮点运算_第1张图片

    正确得到结果。

你可能感兴趣的:(JIT脚本引擎:浮点运算)