随笔-341  评论-2670  文章-0  trackbacks-0
    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 }

    得到如下结果:

    正确得到结果。
posted on 2009-03-06 04:56 陈梓瀚(vczh) 阅读(1470) 评论(0)  编辑 收藏 引用 所属分类: JIT

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理