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) 阅读(1488)
评论(0) 编辑 收藏 引用 所属分类:
JIT