最近认真看了一下Intel的算术库,对其中的SSE2的运用印象深刻.
然后猛然想到 windows 2003在使用FPU87呢,还是SSE2呢?
经过调试,很遗憾,系统使用的是传统的FPU87的指令集,这实在是浪费CPU的能量啊.
于是操起OllyDbg,打开msvcrt.dll,ntdll.dll改写了一些代码.
1._ftol: VC7.1之前编译的函数按默认设置都会调用此函数进行浮点转整形,对于脚本引擎等涉及频繁浮点整形转化的程序很有意义
改写如下:
 cvttsd2si eax, [esp+arg_0]
 retn
2.fabs: VC未开启内联,或低于VC7.1时被调用,用于abs~
改写如下:
fld     qword ptr [esp+4]
fabs
retn
3.
其他浮点函数atan/ceil/exp/floor/log/log10/modf/pow
这些在msvcrt.dll是有开关函数的 _set_SSE2_enable,虽然MSDN说如果CPU支持会自动开启,但是其实是如果CPU支持将允许你启用,不等于自动开启
代码片段:
  77BE1499      8325 845DBF77 00         and     dword ptr [77BF5D84], 0
  77BE14A0      8325 805DBF77 00         and     dword ptr [77BF5D80], 0  // 直接都改成 or 1
  77BE14A7  |.  F645 EB 04               test    byte ptr [ebp-15], 4
  77BE14AB  |.  74 13                    je      short msvcrt.77BE14C0
  77BE14AD  |.  E8 4EFFFFFF              call    msvcrt.77BE1400  //进行无效指令计算
  77BE14B2  |.  85C0                     test    eax, eax
  77BE14B4  |.  74 0A                    je      short msvcrt.77BE14C0
  77BE14B6  |.  C705 845DBF77 01000000   mov     dword ptr [77BF5D84], 1 // 如果支持 77BF5D84 设为1,但是却没有把77BF5D80设为1
  77BE14C0  |>  8B4D FC                  mov     ecx, dword ptr [ebp-4]

OK,这就好办了
or    dword ptr [77BF5D80], 1
这样就强制开启了.
对于ntdll.dll,大部分函数没有SSE2的代码,只有ceil,floor,直接去掉头部的jmp即可.
 
额外的:
vcpkg5.5自带了这个patch,当VC6IDE加载vcpkg时自动patch msvcrt.dll,提升VC6的浮点性能.显然,内存patch仅作用于当前进程,对系统其他进程没有帮助,推荐patch系统文件,这样所有系统中运行的软件都会受益.

对于开发人员:
如果你在用 VC6或可能会调用msvcrt.dll中的浮点运算函数(就算你不调用,系统自身dll也会调用,因为它是 NT CRT DLL),那么显然我们不能去Patch用户计算机中的文件,启动时执行以下代码,有益于提高速度.
调用永远是安全的,因为这个函数会将设置与屏蔽位取与,所以,只有在SSE2指令集的计算机中在最终生效.
  typedef int (_cdecl *PFN_set_SSE2_enable)(int flag);
  PFN_set_SSE2_enable pfn_set_SSE2_enable;
  pfn_set_SSE2_enable=(PFN_set_SSE2_enable)GetProcAddress(GetModuleHandle(_T("msvcrt.dll")),"_set_SSE2_enable");
  if (pfn_set_SSE2_enable) pfn_set_SSE2_enable(1);
 
注意:
1.如果你要跟随这个修改,务必保证你的CPU支持SSE2指令集,否则,.....
2.关掉系统的SFC,否则,会被自动还原
3.ntdll.dll,这类系统dll的修改,记得替换前更新CheckSum,这是好习惯