最近认真看了一下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,这是好习惯
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!