D3DX Math (1): CPU Optimization

来源:互联网 发布:java天气预报接口api 编辑:程序博客网 时间:2024/06/10 01:16

对D3DX的数学函数比较好奇,所以用windbg一探究竟。

先从一个简单的D3DX导出函数D3DXVec4Cross开始吧。

0:000> u d3dx10_42!D3DXVec4Cross
d3dx10_42!D3DXVec4Cross:
697b0276 ff2554637f69    jmp     dword ptr [d3dx10_42!g_D3DXFastTable+0x44 (697f6354)]
697b027c cc              int     3
697b027d cc              int     3
697b027e cc              int     3
697b027f cc              int     3
697b0280 cc              int     3

这个函数通过函数表g_D3DXFastTable的0x44项跳转到了真正的初始化代码。

0:000>  dd d3dx10_42!g_D3DXFastTable+0x44
697f6354  697b025e 697afaaa 697b0eaf 697b24a5
697f6364  697b2565 697b2b0d 697b2be4 697b20e8
697f6374  697b214e 697b2389 697b1362 697b20a2
697f6384  697b20c5 697b22f3 697b13ef 697b148f
697f6394  697b1531 697b12d5 697b2e10 697b27f1
697f63a4  697b2a37 697b0b92 697b1714 697b1878
697f63b4  697b1838 697b18de 697b15d1 697b2970
697f63c4  697b2588 697b2a14 697afa87 697afb9a

0:000> u 697b025e
d3dx10_42!init_D3DXVec4Cross:
697b025e 8bff            mov     edi,edi
697b0260 55              push    ebp
697b0261 8bec            mov     ebp,esp
697b0263 6a01            push    1                                                                                                   ;TRUE, 开启CPU优化
697b0265 e8b9520000      call    d3dx10_42!D3DXCpuOptimizations (697b5523)
697b026a 5d              pop     ebp
697b026b ff2554637f69    jmp     dword ptr [d3dx10_42!g_D3DXFastTable+0x44 (697f6354)]
697b0271 cc              int     3

查MSDN可以知道,D3DXCpuOptimizations的作用是开启或者关闭CPU的浮点计算优化。

D3DXCpuOptimizations

Enables or disables CPU optimizations.

D3DX_CPU_OPTIMIZATION D3DXCpuOptimizations(  BOOL Enable);
Parameters
Enable
[in] TRUE to enable CPU optimizations; otherwise FALSE.
Return Values

Returns the type of CPU detected, and for which optimizations exist (see D3DX_CPU_OPTIMIZATION).

 

 

init_D3DXVec4Cross在调用完这个函数以后,又跳转回函数表g_D3DXFastTable+0x44项。此时这个值已经不再是init_D3DXVec4Cross的地址了,具体是什么值,根据CPU决定。现在我们先看看D3DXCpuOptimizations的代码。

 

0:000> u d3dx10_42!D3DXCpuOptimizations L50
d3dx10_42!D3DXCpuOptimizations:
697b5523 8bff            mov     edi,edi
697b5525 55              push    ebp
697b5526 8bec            mov     ebp,esp
697b5528 51              push    ecx
697b5529 56              push    esi
697b552a 57              push    edi
697b552b e8c8b40300      call    d3dx10_42!D3DX10Debug::D3DX10CheckNewDelete (697f09f8)      ;d3dx DLL使用了C++的new&delete操作符,这个函数检查内存分配行为是否符合C++标准,我们可以无视
697b5530 837d0800        cmp     dword ptr [ebp+8],0                                                                      ;参数是否为0?
697b5534 751e            jne     d3dx10_42!D3DXCpuOptimizations+0x31 (697b5554)
697b5536 c70564657f69ffff0000 mov dword ptr [d3dx10_42!g_CpuOptimization (697f6564)],0FFFFh ;设置全局变量g_CpuOptimization为-1,表示优化暂时关闭
697b5540 6a4a            push    4Ah
697b5542 59              pop     ecx
697b5543 be38647f69      mov     esi,offset d3dx10_42!g_D3DXFastTableC (697f6438)                     ;未优化函数表
697b5548 bf10637f69      mov     edi,offset d3dx10_42!g_D3DXFastTable (697f6310)
697b554d f3a5            rep movs dword ptr es:[edi],dword ptr [esi]                                                   ;拷贝未优化的函数表
697b554f e9bc000000      jmp     d3dx10_42!D3DXCpuOptimizations+0xed (697b5610)                      ;返回
697b5554 813d64657f69ffff0000 cmp dword ptr [d3dx10_42!g_CpuOptimization (697f6564)],0FFFFh   ;优化是否已经开启?
697b555e 0f85ac000000    jne     d3dx10_42!D3DXCpuOptimizations+0xed (697b5610)                     ;返回
697b5564 832564657f6900  and     dword ptr [d3dx10_42!g_CpuOptimization (697f6564)],0
697b556b 6a4a            push    4Ah
697b556d 59              pop     ecx
697b556e be38647f69      mov     esi,offset d3dx10_42!g_D3DXFastTableC (697f6438)
697b5573 bf10637f69      mov     edi,offset d3dx10_42!g_D3DXFastTable (697f6310)
697b5578 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]                                                   ;拷贝未优化的函数表,回到初始状态
697b557a 6810637f69      push    offset d3dx10_42!g_D3DXFastTable (697f6310)
697b557f e8c4fc0000      call    d3dx10_42!x86_D3DXInitFastTable (697c5248)                                   ;针对x86CPU的优化,即使只使用x87 FPU,还是有几个重要的函数用手动汇编代码提高效率,如D3DXMatrixMultiply和D3DXVec3Transform
697b5584 6a04            push    4
697b5586 8d45fc          lea     eax,[ebp-4]
697b5589 50              push    eax
697b558a 6834427969      push    offset d3dx10_42!`string' (69794234)                                            ;”DisableD3DX10PSGP”
697b558f 6a04            push    4
697b5591 e829feffff      call    d3dx10_42!c_D3DXQuaternionSquadSetup+0x499 (697b53bf)               ;这个函数符号有错,功能主要是查注册表Software/Microsoft/Direct3D下当前exe文件的键的DisableD3DX10PSGP的值,PSGP表示Processor Specific Geometry Pipeline。这个键值也是一个开关,决定这个exe文件执行的时候DirectX 10是否开启CPU的SIMD指令集,具体逆向代码就不分析了。
697b5596 85c0            test    eax,eax                                                                                            ;非0表示键值存在
697b5598 7504            jne     d3dx10_42!D3DXCpuOptimizations+0x7b (697b559e)
697b559a 8365fc00        and     dword ptr [ebp-4],0
697b559e 837dfc00        cmp     dword ptr [ebp-4],0
697b55a2 7402            je      d3dx10_42!D3DXCpuOptimizations+0x83 (697b55a6)
697b55a4 eb6a            jmp     d3dx10_42!D3DXCpuOptimizations+0xed (697b5610)                       ;返回
697b55a6 837dfc02        cmp     dword ptr [ebp-4],2
697b55aa 7422            je      d3dx10_42!D3DXCpuOptimizations+0xab (697b55ce)
697b55ac 6a07            push    7                                                                                                  ;PF_3DNOW_INSTRUCTIONS_AVAILABLE=7, IsProcessorFeaturePresent的参数
697b55ae e839ffffff      call    d3dx10_42!c_D3DXQuaternionSquadSetup+0x5c6 (697b54ec)             ;符号又有错。此函数调用IsProcessorFeaturePresent API来判断指令集是否存在
697b55b3 85c0            test    eax,eax
697b55b5 7417            je      d3dx10_42!D3DXCpuOptimizations+0xab (697b55ce)
697b55b7 6810637f69      push    offset d3dx10_42!g_D3DXFastTable (697f6310)
697b55bc e8c5c60200      call    d3dx10_42!amd_D3DXInitFastTable (697e1c86)                          ;使用3D Now指令集优化
697b55c1 59              pop     ecx
697b55c2 c70564657f6901000000 mov dword ptr [d3dx10_42!g_CpuOptimization (697f6564)],1
697b55cc eb42            jmp     d3dx10_42!D3DXCpuOptimizations+0xed (697b5610)                       ;返回
697b55ce 6a0a            push    0Ah                                                                                            ;PF_XMMI64_INSTRUCTIONS_AVAILABLE=10
697b55d0 e817ffffff      call    d3dx10_42!c_D3DXQuaternionSquadSetup+0x5c6 (697b54ec)
697b55d5 85c0            test    eax,eax
697b55d7 7417            je      d3dx10_42!D3DXCpuOptimizations+0xcd (697b55f0)
697b55d9 6810637f69      push    offset d3dx10_42!g_D3DXFastTable (697f6310)
697b55de e8e77c0300      call    d3dx10_42!intelsse2_D3DXInitFastTable (697ed2ca)                  ;使用SSE2指令集优化
697b55e3 59              pop     ecx
697b55e4 c70564657f6902000000 mov dword ptr [d3dx10_42!g_CpuOptimization (697f6564)],2
697b55ee eb20            jmp     d3dx10_42!D3DXCpuOptimizations+0xed (697b5610)
697b55f0 6a06            push    6                                                                                                ;PF_XMMI_INSTRUCTIONS_AVAILABLE=6
697b55f2 e8f5feffff      call    d3dx10_42!c_D3DXQuaternionSquadSetup+0x5c6 (697b54ec)
697b55f7 85c0            test    eax,eax
697b55f9 7415            je      d3dx10_42!D3DXCpuOptimizations+0xed (697b5610)
697b55fb 6810637f69      push    offset d3dx10_42!g_D3DXFastTable (697f6310)
697b5600 e858540300      call    d3dx10_42!intelsse_D3DXInitFastTable (697eaa5d)                   ;使用SSE指令集优化
697b5605 59              pop     ecx
697b5606 c70564657f6903000000 mov dword ptr [d3dx10_42!g_CpuOptimization (697f6564)],3
697b5610 a164657f69      mov     eax,dword ptr [d3dx10_42!g_CpuOptimization (697f6564)]
697b5615 5f              pop     edi
697b5616 5e              pop     esi
697b5617 c9              leave
697b5618 c20400          ret                                                                                                        ;以下无视
697b561b cc              int     3
697b561c cc              int     3
697b561d cc              int     3
697b561e cc              int     3
697b561f cc              int     3
d3dx10_42!D3DX10Math::CMatrixStack::AddRef:
697b5620 8bff            mov     edi,edi
697b5622 55              push    ebp
697b5623 8bec            mov     ebp,esp
697b5625 8b4508          mov     eax,dword ptr [ebp+8]

intelsse_D3DXInitFastTable intelsse2_D3DXInitFastTable amd_D3DXInitFastTable三个函数所做的事情无非就是一长串mov操作,把对应的函数地址放入函数表g_D3DXFastTable。具体代码就不再分析了。

现在再看看运行完D3DXCpuOptimizations之后,函数表g_D3DXFastTable第0x44项的值是什么:

0:000> dd d3dx10_42!g_D3DXFastTable+0x44
697f6354  697ed8ac 697eb5f1 697ed5ff 697ebd68
697f6364  697eb204 697ed558 697eb782 697b210b
697f6374  697b2171 697ede60 697b13a2 697eda66
697f6384  697edb63 697b2326 697b141f 697b14bf
697f6394  697b1561 697b1315 697eacb2 697b2827
697f63a4  697b2a78 697b0bb5 697b1737 697b4528
697f63b4  697b44e8 697b1917 697b1604 697b29ac
697f63c4  697edde5 697b4f26 697edcfb 697eb35e
0:000> u 697ed8ac
d3dx10_42!intelsse2_D3DXVec4Cross:
697ed8ac 8bff            mov     edi,edi
697ed8ae 53              push    ebx
697ed8af 8bdc            mov     ebx,esp
697ed8b1 51              push    ecx
697ed8b2 51              push    ecx
697ed8b3 83e4f0          and     esp,0FFFFFFF0h
697ed8b6 83c404          add     esp,4
697ed8b9 55              push    ebp

这就是在INTEL Q6600 CPU上面的运行结果:使用SSE2指令集优化。

好了,这次就写到这里,下次再分析具体的运算代码。